一道腾讯校招试题

题目:

猴子摘香蕉一次可以摘1个或2个,总共50个,有多少种摘法?


分析:

得到如下规律


wKioL1Urj4XTB0qLAALBOYxo7ts034.jpg


实际上是一个斐波那契数列

以下为我使用的4种解法,分别是递归、迭代、64位整型数、 数组(类似于大数相加)。


代码1: 递归

//其中加入了计时器

#include <iostream>
#include <ctime>

using namespace std;

int f(int n)
{
	if(n<=0)
		return 0;
	else if(1==n || 2==n)
		return n;
	else 
		return f(n-1)+f(n-2);
	
}

int main()
{
	double n;
	clock_t t;

	cin>>n;
	cout<<f(n)<<endl;    //我的机子是32位,算不出来,改成long也不行,改成double会丢失精度
	t=clock();
	cout<<t<<endl;    //可以看到,花费的时间非常非常的长。。。。。
	return 0;
}


运行结果1:

//实际上根本算不出来,因为机器年龄大了。。。。哈哈

wKiom1UrhRqRqYHqAABqxJJRkQw032.jpg

只能再找一种更高效的算法 


(⊙o⊙)…等下,它出来了。。。。

wKiom1UrhfnzswGYAACy8Y05MC4759.jpg可以看到,溢出了!


代码2: 迭代

#include <iostream>
#include <ctime>

using namespace std;

int main()
{
	double n,i,a,b,c;
	clock_t t;
	a=1;
	b=2;
	cin>>n;
	if(n<=0)
		cout<<0<<endl;
	else if(1==n || 2==n)
		cout<<n<<endl;
	else
	{
		for(i=2;i<n;i+=2)
		{
			a=a+b;
			b=a+b;
		}
		c=(1==(int)n%2) ? a:b;
		t=clock();
		cout<< c <<endl;
		cout<< t <<endl;
	}
	return 0;
}


运行结果2:

wKiom1Urh82C9HSfAACTTX5kO_s050.jpg

速度快了很多,但在我用的编译器(VC++6.0)下丢失精度


对了,中间还尝试过使用 __int64

这个东西以前也没用过,临时百度的。试了一下,竟然OK了


代码如下:

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
//#include <stdint.h>
#include <ctime>

using namespace std;

int main()
{
	int n,i;
	__int64 a,b;
	clock_t t;
	a=1;
	b=2;
	cin>>n;
	if(n<=0)
		cout<<0<<endl;
	else if(1==n || 2==n)	
		cout<<n<<endl;
	else
	{
		for(i=2;i<n;i+=2)
		{
			a=a+b;
			b=a+b;
		}
		if(n%2)
			printf("%I64d\n",a);
		else
			printf("%I64d\n",b);
		
		t=clock();
		cout<< t <<endl;
	}
	return 0;
}

运行结果:

wKioL1UrjDKiFQcKAACHlW5YT5U556.jpg


然后就想,也许用数组来做也行。空间换时间


代码3: 数组(类似于大数相加)

#include <iostream>
#include <cstring>
#include <ctime>

using namespace std;

int main()
{

	int n,i,j,k;
	int a[50][20];
	clock_t t;

	memset(a,0,sizeof(a));

	a[0][0]=1;
	a[1][0]=2;

	for(i=2;i<50;i++)
	{
		for(j=0,k=0;j<20;j++)
		{
			a[i][j]=(a[i-1][j]+a[i-2][j]+k)%10;
			k=(a[i-1][j]+a[i-2][j]+k)/10;
		}
	/*	k=19;
		while(0==a[i][k])
			k--;
		while(k>=0)
		{
			cout<<a[i][k];
			k--;
		}
		cout<<endl;*/
	}


	cin>>n;

	while(n<=0)
		cin>>n;

	i=19;
	while(0==a[n-1][i])
		i--;
	while(i>=0)
	{
		cout<<a[n-1][i];
		i--;
	}
	cout<<endl;

	t=clock();
	cout<< t <<endl;

	return 0;
}


运行结果3:

wKioL1UrjdbhooqGAACdzus9d0k923.jpg

结果正确,速度也很快!


代码3的改进版

#include <iostream>
#include <cstring>
#include <ctime>
 
using namespace std;
 
int main()
{
 
    int n,i,j,k,l;
    int a[50][20];
    clock_t t;
 
    memset(a,0,sizeof(a));
 
    a[0][0]=1;
    a[1][0]=2;
 
	l=0;
    for(i=2;i<50;i++)
    {
        for(j=0,k=0;j<=l;j++)
        {
            a[i][j]=(a[i-1][j]+a[i-2][j]+k)%10;
            k=(a[i-1][j]+a[i-2][j]+k)/10;
        }
		
		while(k)                //这样可以避免计算高位为0的数字
		{
			a[i][++l]=k%10;
			k/=10;
		}
    /*  k=19;
        while(0==a[i][k])
            k--;
        while(k>=0)
        {
            cout<<a[i][k];
            k--;
        }
        cout<<endl;*/
    }
 
 
    cin>>n;
 
    while(n<=0)
        cin>>n;
 
    i=19;
    while(0==a[n-1][i])
        i--;
    while(i>=0)
    {
        cout<<a[n-1][i];
        i--;
    }
    cout<<endl;
 
    t=clock();
    cout<< t <<endl;
 
    return 0;
}



附图:

wKioL1Urjy-jQb9nAAJeUOj9KOk022.jpg

你可能感兴趣的:(C++,腾讯,校招)