C语言中的递归问题——爬楼梯问题
爬楼梯问题:
这个程序解决的是经典的爬楼梯问题:每次可以爬1级或2级台阶,计算到达第n级台阶有多少种不同的方法。
方法思路:
- 问题分析:这个问题遵循斐波那契数列的规律。到达第n级台阶的方法数是到达第n-1级和第n-2级台阶方法数的和。
- 基本情况:
- 只有1级台阶时,只有1种方法。
- 有2级台阶时,有2种方法(1+1或2)。
- 迭代解决方案:使用循环从3到n逐步计算,避免递归带来的重复计算问题,提高效率。
代码:
#include <stdio.h>int steps(int n)
{if (n == 1){return 1;}else if (n == 2){return 2;}else{return steps(n - 1) + steps(n - 2);//第一步走1级的走法+第一步走2级的走法}
}int main()
{int step = 0 ,number = 0;scanf("%d", &step);number = steps(step);printf("%d\n",number);return 0;
}
代码结构分析:
有一个函数
steps(int n)
,它递归地计算到达第n步的方法数。main
函数中读取用户输入的步数step
,调用steps
函数,并打印结果。
现在,分析 steps
函数:
如果
n == 1
,返回1。因为只有1步时,只有一种方式:走1步。如果
n == 2
,返回2。因为有两种方式:一次走1步两次,或一次走2步。否则,返回
steps(n-1) + steps(n-2)
。这基于这样的逻辑:要到达第n步,可以从第n-1步走1步,或者从第n-2步走2步。所以,到达n步的方法数是到达n-1步和n-2步的方法数之和。
这实际上是一个斐波那契数列的变体。标准的斐波那契数列是F(0)=0, F(1)=1, F(2)=1, F(3)=2, 但这里是从1和2开始,所以序列是1, 2, 3, 5, 8, ... 这对应于斐波那契数列的偏移:F(n) = fib(n+1),其中fib是标准斐波那契。
然而,代码使用递归实现,这会导致效率问题。因为递归会重复计算许多子问题。例如,计算steps(5)时,会计算steps(4)和steps(3),而steps(4)又会计算steps(3)和steps(2),所以steps(3)被计算了多次。时间复杂度是指数级的,O(2^n),这对于较大的n值会非常慢。
在main函数中,读取输入step,调用steps(step),并打印结果。但需要注意的是,如果step值较大,比如大于40,递归会导致大量的函数调用,可能会耗尽栈空间或运行非常慢。
另外,代码没有处理输入错误的情况,比如如果输入负数或0,steps函数会进入无限递归或错误状态,因为递归没有基线条件对于n<=0。所以,代码应该添加输入验证。
总结,代码的逻辑正确,但效率低下,不适合大输入。建议使用迭代或动态规划来优化。
用迭代法求:
爬楼梯问题遵循斐波那契数列。定义f(n)为爬n级台阶的方法数。
当n=1时,只有1种方法:走1步。
当n=2时,有2种方法:走两次1步,或一次走2步。
对于n>2,考虑第一步:
如果第一步走1步,那么剩下的n-1步有f(n-1)种方法。
如果第一步走2步,那么剩下的n-2步有f(n-2)种方法。
因此,总方法数f(n) = f(n-1) + f(n-2)。这正是斐波那契数列的递推关系。但注意,标准的斐波那契数列通常定义为F(0)=0, F(1)=1, F(2)=1, F(3)=2, 等等。而这里f(1)=1, f(2)=2, 所以f(n)实际上对应斐波那契数列的F(n+1)。例如:
f(1)=1 对应 F(2)=1
f(2)=2 对应 F(3)=2
f(3)=f(2)+f(1)=2+1=3 对应 F(4)=3
依此类推。
在代码中,使用迭代方法计算f(n),从f(1)和f(2)开始,逐步计算到f(n)。这避免了递归的重复计算,效率更高。
所以,算法是斐波那契数列的应用,只是起始点略有不同。
这个算法之所以是斐波那契数列,是因为爬楼梯问题的递推关系与斐波那契数列的递推关系完全相同。
代码:
#include <stdio.h>long long steps(int n)
{if (n == 1) return 1;if (n == 2) return 2;long long a = 1, b = 2, c = 0;for (int i = 3; i <= n; i++) {c = a + b;a = b;b = c;}return b;
}int main() {int n;scanf("%d", &n);printf("%lld\n", steps(n));return 0;
}
补充:
变量初始化:
a = 1
:表示到达第n-2级台阶的方法数(初始为到达第1级的方法数)b = 2
:表示到达第n-1级台阶的方法数(初始为到达第2级的方法数)c = 0
:用于临时存储计算结果
循环逻辑:
循环从3开始到n结束,因为前两种情况已经在基线条件中处理
每次迭代中:
c = a + b
:计算到达当前台阶i的方法数(等于前两级和前一级方法数之和)a = b
:更新a为前一级的方法数(为下一次迭代做准备)b = c
:更新b为当前级的方法数(为下一次迭代做准备)
返回值:循环结束后,b中存储的就是到达第n级台阶的方法数