走台阶问题

1,假设有n个台阶的楼梯,一个人要上这个楼梯,他每次可以走1个台阶或者2个台阶,问走上这个楼梯的走法总共有多少种?

   解答:这个题目可以从最简单的办法逐步掌握其规律,比如走上1个台阶总共只有1种走法,而走上2个台阶有两种走法(一种直接走2步,一种走2个一步),我们知道要走上第i个台阶,要么是从第i-1个台阶走一小步到的,要么是从第i-2个台阶走1大步。用F(i)表示走上第i个台阶的走法总数,那么F(1)=1,F(2)=2,那么F(i)是依赖于F(i-1)和F(i-2)的,其中 2<i<=n, 我们很容易知道 F(i)=F(i-1)+F(i-2)。也就是说我们最终问题的解为F(n)=F(n-1)+F(n-2),F(1)=1,F(2)=2.  了解斐波那契数列的人就知道这明显就是一个斐波那契数列。

可以通过方程递归的求解问题:

int Step(int n)//递归
{
    if(n==1)
        return 1;
    else if (n==2)
        return 2;
    else 
        return Step(n-1)+Step(n-2);
}

这个过程的时间复杂度为O(2^n),我们可以用循环递推来改变这个时间代价:

int func(int n)//时间复杂度是O(n)
{
    int *a = new int[n];
    a[0] = 1;
    a[1] = 2;
    for (int i = 2;i<n;i++)
    {
        a[i] = a[i - 1] + a[i - 2];
    }
    int res = a[n - 1];
    delete[] a;
    return res;
}

对以上俩函数进行测试对比:

#include<iostream>
#include<time.h>
using namespace std;

int step(int n);//递归

int func(int n);//改进

int main(void)
{
    clock_t start, finish;
    double  t1,t2;
    int ditui,diaoyong;
    start = clock();
    diaoyong= step(30);//假设30台阶
    cout << diaoyong << endl;
    finish = clock();
    t1 = (double)(finish - start) / CLOCKS_PER_SEC*1000000;
    cout <<"函数循环调用使用了"<< t1 << " 微秒" << endl;
    
    start = clock();
    ditui = func(30);
    cout << ditui << endl;
    finish = clock();
    t2= (double)(finish - start) / CLOCKS_PER_SEC * 1000000;
    cout <<"数组递推使用了"<< t2 << " 微秒" << endl;
    return 0;
}

测试结果对比

2.一个人上台阶可以一次上1个,2个,或者3个,问这个人上n层的台阶,总共有几种走法?

同样地我们也可以使用上述方法:

//函数递归调用
int step(int n)
{
    if (n == 1)
        return 1;
    else if (n == 2)
        return 2;
    else if (n == 3)
        return 4;
    else
        return step(n - 1) + step(n - 2)+ step(n - 3);
}
//数组循环
int func(int n)
{
    int *a = new int[n];
    a[0] = 1;
    a[1] = 2;
    a[2] = 4;
    for (int i = 3;i<n;i++)
    {
        a[i] = a[i - 1] + a[i - 2]+ a[i - 3];
    }
    int res = a[n - 1];
    delete[] a;
    return res;
}
原文地址:https://www.cnblogs.com/Burgess-Fan/p/6803923.html