我一直在解决一些面试问题,我正在努力确定某些递归函数的运行时间。 我正在解决的问题是:
想象一下,机器人坐在X by Y网格的左上角。 机器人只能向两个方向移动:向右和向下。多少 机器人从(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&lt; 0或Y&lt; 0的调用以提高可读性):
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次递归调用。
这让我更加怀疑自己的直觉。
有人可以帮我分析这个(和类似的)递归函数来确定时间复杂度吗? 我不是在寻找你们这些人如何解决这个问题的深度解释,但也许是一些一般的指示或建议?感谢。
答案 0 :(得分:0)
当每个summand为S
或0
时,总和1
需要多少个加数?嗯,显然至少S
。因此,您的函数至少会进行answer
次调用,其中answer
是问题的答案。如果你只返回那些,那将是确切的计数,否则处理零。
为了记录,问题的一个很好的解决方案与Pascal's Triangle有很大关系(这个picture可能有帮助)。
答案 1 :(得分:0)
有一个更简单的解决方案:要从(0,0)到(x,y),它必须总共采取x + y步。在那些你必须选择x水平步骤的位置,你可以用二项式(x + y,x)方式。
答案 2 :(得分:0)
整蛊,每个问题都不一样。从一个电子表格开始,该电子表格计算调用问题的调用次数。
如果您从X = Y&gt;开始0,做递归调用X + Y级别深度,然后有2 ^(X + Y)种方式可以选择两个递归调用。许多方法不会深入X + Y水平,因为X或Y变为负数。但是如果你按照每个呼叫路径进行相同的次数,那么你将深入到X + Y级别。有(超过X的2倍)方法,大约是2 ^(X + Y)/ sqrt(pi X)。