大一时的一道C语言练习题,可作为递归和尾递归转迭代的范例。HDU 2013 http://acm.hdu.edu.cn/showproblem.php?pid=2013
题意:猴子摘了sum个桃子,从第1天开始,每天吃掉剩余桃子的一半多一个,第n天时只剩1个桃子,求sum值。
分析:设第 i 天在开吃之前所剩的桃子数为sum(i),第 i 天要吃掉的桃子数为f(i),
则问题可表示为:已知sum(n)=1 和如下两个关系式:
f(i) = sum(i)/2 + 1 (1)
sum(i+1) = sum(i) - f(i) (2)
求sum(1)。
求解:(1)(2)式联立,可得递推式sum(i+1) = 2*sum(i) + 2。加上递归基sum(n)=1,可直接写出如下递归函数:
1 int sum(int x){ 2 if(x==n) return 1; 3 return 2*sum(x+1) + 2; 4 }
在主函数中调用sum(1)即可得答案。
上面的递归函数属于尾递归(递归调用在最后一步),可以比较直观地转成迭代形式。只需从递归基出发进行n-1次迭代,即可得到同样的结果。代码如下:
1 ans=1; 2 int i=1; 3 while(i++ < n){ 4 ans = 2*ans + 2; 5 }
这道题的迭代相比递归,省去了n-1层调用栈,空间复杂度从O(n)降到O(1),时间复杂度仍为O(n)未变。
原文:http://www.cnblogs.com/helenawang/p/5151360.html