n级台阶 1,2,3 步走法

转自:http://blog.csdn.net/eagleatustb/article/details/6834057


最近看到一批面试题目,比较感兴趣,工作之余解解题来练习练习思维.

人人笔试1:一个人上台阶可以一次上1个,2个,或者3个,问这个人上n层的台阶,总共有几种走法?
思路:先建立数学模型,设3步的走 i 次,2步的走 j 次, 1步的走 k 次,上了3*i + 2*j + 1*k = n个台阶.总共走 i + j + k 次, 等于把n个台阶的长度先划分成 i + j + k 个段落, 然后分别填下i个3, j 个2, k个1.这样,当划分成 i + j + k 个段落时, 根据排列组合知识,所有填充方法有 (i + j + k )!/ ( i!*j!*k!) 种,程序中使用GetComb(i,j,k)函数计算此值.
对于i, j, k的确定,我们可以用从大到小划分法, 先划分3的次数,再划分2的次数,剩下的都算做1的次数,具体程序中就是里面的i,j,两重循环.


 
[cpp] view plaincopy
//辅助函数,计算阶乘  
int Factorial(int n)  
{  
 int ret = n;  
 if (n<=1)  
 {  
  return 1;  
 }  
 while (n-->1)  
 {  
  ret*=n;  
 }  
 return ret;  
}  
  
  
//求(i+j+k)!/(i!*j!*k!)  
  
int GetComb(int i,int j,int k)  
{  
 int result = 1;  
 int m = Factorial(i+j+k);  
 int l =  Factorial(i)*Factorial(j)*Factorial(k);  
 return m/l;  
}  
  
//主函数  
  
int NStepFor123(int n)  
{  
    int i=0;  
    int j=0;  
    int p;  
    int k;  
    int result=0;  
    for ( i=0; i<=n/3; i++ )  
    {  
        p = n-i*3;  
        for ( j=0; j<=p/2; j++ )  
        {  
            k = p -j*2;  
            //求(i+j+k)!/(i!*j!*k!)  
            result += GetComb(i,j,k);  
        }  
    }  
    return result;  
}  
 
另外有一种数学归纳法的思路先得出递推式:
f(n) = f(n-1)+f(n-2)+f(n-3),特别地f(0)=1;f(1)=1;f(2)=2;
式子的证明为:增加一步共为f(n+1)的时候,把这新的一步算进去后有三种情况,1是这一步仅当一步走为f(n)次,2是这一步配合原来的最后一步作为两步走为f(n-1)次,3是这一步配合前面的两步作三步走为f(n-2);所以式子f(n+1) =f(n)+ f(n-1)+f(n-2),归纳得证。
这种方法可以使复杂度降为O(n),而且只有加法,比上面的第一种方法要好。计算f(n)只要一直记录之前三个值,以求下一个值就可以了。以下是程序实现:
[cpp] view plaincopy
int f (int k)  
{  
    int v[3]={1,1,2};  
    int index = -1;  
    int i = 0;  
  
    if (k<0)  
    {  
        return 0;  
    }  
  
    if (k<3)  
    {  
        return v[k];  
    }  
  
    while(k-->2)  
    {  
        index++;  
        index %= 3;  
        v[index] = v[0]+v[1]+v[2];        
    }  
    return v[index];  
}  

猜你喜欢

转载自blog.csdn.net/cyyingsun/article/details/8635528
今日推荐