【问题标题】:Running time of a recursive function with two inputs具有两个输入的递归函数的运行时间
【发布时间】:2014-03-23 20:30:17
【问题描述】:

我一直在解决一些面试问题,练习,但我仍然在努力确定一些递归函数的运行时间。 我要解决的问题是:

想象一个机器人坐在 X x Y 网格的左上角。 机器人只能在 2 个方向上移动:向右和向下。多少 机器人从 (0, 0) 到 (X, Y) 有可能的路径吗?

我的解决方案(Java):

public int totalPossiblePaths(int X, int Y) {
    if(X < 0 || Y < 0) {
        return 0;
    }
    if(X == 0 && Y ==0) {
        return 1;
    }
    return totalPossiblePaths(X - 1, Y) +
           totalPossiblePaths(X, Y - 1);
}

此外,我对这个程序的空间和时间复杂度进行了分析,就大哦而言,因为面试需要我知道。 我得出的结论是空间复杂度是:

O(X + Y)

由于最多有 X 次递归调用,然后是 Y 次递归调用,因此最多 X+Y 次函数调用将被压入堆栈。

但是,运行时间复杂度对我来说不是很清楚。 我已经绘制了递归树,很明显递归是(至少)指数的。 我似乎无法确定 X 和 Y 之间的关系。

示例递归(没有调用 X

    F(3, 2) = F(2, 2) + F(3, 1)
            = F(1, 2) + F(2, 1) + F(2, 1) + F(3, 0)
            = F(0, 2) + F(1, 1) + F(1, 1) + F(2, 0) + F(1, 1) + F(2, 0) + F(2, 0)
            = F(0, 1) + F(0, 1) + F(1, 0) + F(0, 1) + F(1, 0) + F(1, 0) + F(0, 1) + F(1, 0) + F(1, 0) + F(1, 0)
            = F(0, 0) + F(0, 0) + F(0, 0) + F(0, 0) + F(0, 0) + F(0, 0) + F(0, 0) + F(0, 0) + F(0, 0) + F(0, 0)

最后一级有 10 个元素(返回值 1),即从 (0, 0) 到达 (3, 2) 的可能路径数。 根据我的直觉,我认为运行时间相对于 X 和 Y 会增长:

O(2^X * 2^Y) = O(2^(X + Y))

此外,我添加了一个计数器,它随着每次递归调用而递增,以查看函数被调用了多少次。对于上面的例子,函数被调用了 49 次。 该函数成功传递了两个if 语句24 次,并尝试再进行2 次递归调用。

这让我更加怀疑自己的直觉。

谁能帮我分析这个(和类似的)递归函数来确定时间复杂度? 我不是在找你们费心向我解释如何解决这个问题,但也许是一些一般性的指示或建议?谢谢。

【问题讨论】:

  • 我怀疑预期的方法是您采用的方法。从左上角到右下角的路径总是由X+Y 向下 (D) 或向左 (L) 步组成,其中 X 向左走,Y 向向下走。例如,对于X = 3Y = 2,这是一种可能的路径:LLDLD。问题是:存在多少种不同的序列?换句话说,你有多少种方法可以从X+Y 位置中选择XL?组合学告诉这是X+Y choose X,或(X+Y)!/(X!Y!)
  • 是的,你是对的。我的解决方案只是通过向左和向上移动从 (X, Y) 向后移动到 (0, 0),这与从 (0, 0) 开始并通过向右和向下移动到 (X, Y) 是相反的。对于 X = 3 和 Y = 2,我的解是 10。(X + Y)! / (X!Y!) 将给出 (5)! / (3!2!) = 10
  • 在我看来就像 Ramsey numbers 的递归。这些增长很快。

标签: algorithm recursion complexity-theory


【解决方案1】:

棘手,每个问题都是不同的。从计算调用次数的电子表格开始,以了解问题。

如果你从 X = Y > 0 开始,递归调用 X + Y 级别很深,那么你可以选择两种递归调用中的 2^(X + Y) 种方式。许多这些方法不会深入 X + Y 级别,因为 X 或 Y 变为负数。但是,如果您按照相同的次数跟踪每个调用路径,那么您将深入 X + Y 级别。有 (2X over X) 方法可以做到这一点,大约是 2^(X + Y) / sqrt (pi X)。

【讨论】:

  • 谢谢。这与我正在寻找的内容一致。
  • 你能解释一下 pi*X 的根是哪里来的吗?这是斯特林近似的应用吗?另外,Y 如何成为 X 的 2X 的术语?
  • 是的,任何进一步的解释都非常感谢:)
  • 啊,找到了,你还在说 if X = Y;那么你给出的实际上是应用斯特林近似的结果,可以在on wiki找到。
【解决方案2】:

当每个 summand 都是 01 时,需要多少 summands 才能得到 sum S?好吧,显然至少是S。因此,您的函数至少会进行answer 调用,其中answer 是问题的答案。如果你只返回一个,那将是准确的计数,否则处理零。

郑重声明,问题的一个好的解决方案与Pascal's Triangle 有很大关系(这个特殊的picture 可能会有所帮助)。

【讨论】:

    【解决方案3】:

    有一个更简单的解决方案:从 (0, 0) 到 (x, y) 总共需要 x + y 步。其中,您必须选择 x 个水平步骤的位置,您可以通过二项式 (x + y, x) 方式进行操作。

    【讨论】:

    • 感谢你们提供替代解决方案。它绝对可以帮助我从不同的角度看待问题。但是,我想找到我创建的解决方案的运行时间,而不是特别是如果它是最佳的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-28
    • 2020-10-05
    • 1970-01-01
    • 2013-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多