Climbing Stairs爬楼梯啊爬楼梯(支持n step)

leetcode原题


You are climbing a stair case. It takes n steps to reach to the top.

Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?


就是有个n阶的楼梯,你一次可以爬一阶或者两阶,有多少种爬法。


一眼看上去很简单嘛,简单的递归就搞定了:

class Solution {
public:
	int climbStairs(int n) {
		cl(n);
		return sum;
	}
	void cl(int n)
	{
		if (n<=0)
		{
			if (n == 0)
				sum++;
			return;
		}
		cl(n - 1);
		cl(n - 2);
	}
	int sum = 0;
}

思路应该不用太多解释,就是没递归一次都分爬一阶、两阶两种情况,爬完就++。真是sometimes naive,果断超时……


第二版:

这一定是递归的问题嘛,把递归去掉就好了。用两个容器,把每次爬的两种情况都记录下来,一个用来记录上次爬完后各种情况剩余的阶数,一个用来记录新的阶数。

这次再有点追求,step不止是2,n步也可以的嘛。

int climbStairs2(int n)
{
	vector<int>ways;
	vector<int>oldways;
	int steps = 2, sum = 0;

	oldways.push_back(n);
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j != oldways.size(); j++)
		{
			if (oldways[j] > 0)
			{
				for (int k = 1; k <= steps && k <= oldways[j]; k++)
				{
					if (oldways[j] - k == 0)
						sum++;
					else
						ways.push_back(oldways[j] - k);
				}
			}
		}
		oldways = ways;
		ways.clear();
		vector<int>().swap(ways);
	}
	return sum;
}

-,-还是超时啊,能不能再给力一点啊老湿,这都o(n^2),完全没什么效率的提升啊。


第三版:

设n阶的爬法为f(n) ,很显然f(n+1)= f(n) + f(n-1).

因为最后一步只有两种情况,从n阶跨一阶或者从n-1阶跨两阶。

这次效率真提高了,时间复杂度0(n)

int climbStairs3(int n)
{
	if (n <= 0)
		return 0;
	int x0 = 0, x1 = 1;
	for (int i = 1; i <= n; i++)
	{
		int tmp = x1;
		x1 += x0; 
		x0 = tmp;
	}
	return x1;
}

这次是a掉了,不过说好的n step都支持呢?能不能再给力一点啊老湿?


第四版:

如果最大step为m的话,每次就有m种情况,所以f(n) =  f(n-1) + f(n-2) + f(n-3).……+f(n-m).


可以用一个双向队列来保存,这m种情况。每次计算完后,把结果push back,然后pop front把头去掉,就可以吃了。

这里要注意一下当阶数小于step时的情况,

比如当阶数为i, 最大step为maxstep,当前step为j,

当i < j 的时候,自然没有f(i - j)的情况,边界情况为i == j的时候。

所以f(i) == f(j) ,但这时的f (j)除了要加上前面的f (i - j +1) f (i - j + 2) ……f(j-1) 还需要加1, 因为要加上从0直接跨i步到达i阶的2情况。

int climbStairs4(int n)
{
	if (n <= 0)
		return 0;
	const static int maxStep = 2;
	int sum = 0;
	deque<int>ways(maxStep, 0);
		
	for (int i = 1; i <= n; i++)
	{
		sum = 0;
		for (int j = 1; j <= maxStep && j<= i; j++)
		{
			if (i>j)
				sum += ways[maxStep - j];
			if (i == j)
				sum++;
		}
		ways.pop_front();
		ways.push_back(sum);
			
	}
	return ways.back();
}

PS:这个其实就是费波拉契数列的求和,有直接的求和公式的。还有各种矩阵运算什么的……没有太花心思在上面呢。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值