【发布时间】: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 = 3和Y = 2,这是一种可能的路径:LLDLD。问题是:存在多少种不同的序列?换句话说,你有多少种方法可以从X+Y位置中选择X次L?组合学告诉这是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