问题描述:
假设一个人一次可以走一个台阶或者一次走两个台阶,问走到第n个台阶共有多少种走法?
例如,用数字表示一次所走台阶数,那么,
第1个台阶,走法有1 共1种走法;
第2个台阶,走法有1-1、2 共2种走法;
第3个台阶,走法有1-1-1、1-2、2-1 共3种走法;
第4个台阶,走法有1-1-1-1、1-2-1、1-1-2、2-1-1、2-2 共5中走法
……
由此,首先想到的是递归算法
一、递归算法思想:
假设用Steps(n)表示走到第n个台阶时的走法种数,则有两种情况:
(1)走到第n个台阶可以是从第n-1个台阶走上来的,一次走一一个台阶;
(2)走到第n个台阶可以是从第n-2个台阶走上来的,一次走两个台阶。
那么Steps(n)可表示成Steps(n)=Steps(n-1)+Steps(n-2),符合问题描述。
递归案例效果:
完整递归代码实现:
#include<stdio.h>
#include<stdlib.h>
int Steps(int n)
{
if (1 == n)
return 1;
else if (2 == n)
return 2;
else
return Steps(n - 1) + Steps(n - 2);
}
int main()
{
int n;
while (scanf("%d", &n) != EOF)
{
printf("台阶数为%d时,有%d种走法\n",n,Steps(n));
}
system("pause");
}
二、非递归思想:
任何递归都可以拆成非递归实现,非递归的过程实质上就是递归算法的进一步细化拆分。
设fir表示走第1个台阶的走法,则fir=1;sec表示走第2个台阶的走法,则sec=2。当走到第3个台阶时,可以表示成steps=fir+sec=3;同时将sec赋值给fir,steps赋值给sec,便于走到下一个台阶时进行计算。则将上述递归算法部分可以拆分如下:
fir = 1;
sec = 2;
if (1 == n)
steps = fir;
else if (2 == n)
steps = sec;
else
{
for (int i = 3; i <=n; i++)
{
steps = fir + sec;
fir = sec;
sec = steps;
}
}
可以利用斐波拉契思想,通过改变fir和sec的初值,将if条件语句部分融入for循环语句中,使得for循环包含前两种情况,如下改写:
fir = 0;
sec = 1;
for (int i = 1; i <=n; i++)
{
steps = fir + sec;
fir = sec;
sec = steps;
}
则递归转化非递归完成。
运行效果如下:
完整的非递归算法代码:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int fir, sec, steps;
int n;
while (scanf("%d", &n) != EOF)
{
fir = 0;
sec = 1;
for (int i = 1; i <= n; i++)
{
steps = fir + sec;
fir = sec;
sec = steps;
}
printf("走到第%d个台阶共有%d种走法", n, steps);
}
system("pause");
}