爬楼梯问题/上台阶问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014485485/article/details/82532130

商汤科技的笔试题。n阶,步长1~m,有时间和内存限制。

基础题:

n阶楼梯,每次能走1或2阶,问走到n阶一共多少种走法。

法一:递归 很容易超时

f(0)=1,f(1)=1,f(n)=f(n-1)+f(n-2)

#include <stdio.h>
#include <iostream>
#include<Windows.h>
using namespace std;

long long climbStairs(int n)
{
	if (n == 1)
		return 1;
	else if (n == 2)
		return 2;
	else if (n > 2)
		return climbStairs(n - 1) + climbStairs(n - 2);
}

int main()
{
	long long stepCount = 0;

	DWORD start_time = GetTickCount();
	stepCount = climbStairs(45);  //40: 165580141 4.88s 45: 1836311903 53.99s
	DWORD end_time = GetTickCount();

	printf("%lld\n", stepCount);
	cout << "The run time is: " << (end_time - start_time) / 1000.0 << " s!" << endl;
	getchar();
	return 0;
}

法二:递推 用空间换时间,避免了重复计算,时间快了很多倍

#include <stdio.h>
#include <iostream>
#include<Windows.h>
using namespace std;

long long step[101] = { 0 };
long long climbStairs(long long step[], int n)
{
	if (n <= 0)
		return 0;
	step[0] = 1;//人为规定
	step[1] = 1;

	if (n >= 2)
	{
		for (long long i = 2; i <= n; i++)
		{
			step[i] = step[i - 1] + step[i - 2];
		}
	}
	return step[n];
}

int main()
{
	long long stepCount = 0;

	DWORD start_time = GetTickCount();
	stepCount = climbStairs(step, 40);
	DWORD end_time = GetTickCount();

	printf("%lld\n", stepCount);
	cout << "The run time is: " << (end_time - start_time) / 1000.0 << " s!" << endl;
	getchar();
	return 0;
}

法三:找数学规律 类似于递推 求得通项 [Xn Xn-1]=[Xn-1+Xn-2;Xn-1]=...=[1 1;1 0]^(n-1) * [1 1]

#include <stdio.h>
#include <iostream>
#include<Windows.h>
using namespace std;

long long climbStairs(int n)
{
	int a11 = 1, a12 = 1, a21 = 1, a22 = 0;
	int v1 = 1, v2 = 1;
	int x1 = 1, x2 = 1;
	for (int i = 1; i < n; i++)
	{
		x1 = a11*v1 + a12*v2;
		x2 = a12*v1 + a22*v2;
		v1 = x1;
		v2 = x2;
	}

	return v1;
}

int main()
{
	long long stepCount = 0;

	DWORD start_time = GetTickCount();
	stepCount = climbStairs(40);
	DWORD end_time = GetTickCount();

	printf("%lld\n", stepCount);
	cout << "The run time is: " << (end_time - start_time) / 1000.0 << " s!" << endl;
	getchar();
	return 0;
}

拓展:N阶台阶,每次可以走1~m步

法一:递归 时间容易超

#include <stdio.h>
#include <iostream>
#include<Windows.h>
using namespace std;

long long climbStairs(int n, int m) {
	int stepsCount = 0;
	if (n == 0) {
		return 1;
	}
	
	if (n >= m) {// 总剩余的台阶数n大于步长m
		for (int i = 1; i <= m; i++) {
			stepsCount += climbStairs(n - i, m);
		}
	}
	else {// 剩余台阶数n小于步长m
		stepsCount += climbStairs(n, n);
	}
	return stepsCount;
}

int main()
{
	long long stepCount = 0;

	DWORD start_time = GetTickCount();
	stepCount = climbStairs(45,2);//40:165580141 14.898s 45:1836311903 166s
	DWORD end_time = GetTickCount();

	printf("%lld\n", stepCount);
	cout << "The run time is: " << (end_time - start_time) / 1000.0 << " s!" << endl;
	getchar();
	return 0;
}

上面这个代码太初级,只能解决n和m都很小的情况,通过了50%。题目中实际要求时间<=2s。

需要优化。待更新。

Reference:https://blog.crayygy.com/14599905787744.html

猜你喜欢

转载自blog.csdn.net/u014485485/article/details/82532130