【LeetCode】遇到一个很有趣的问题:Climbing Stairs


这个问题简单说来是这样的:你上楼梯可以选择一次迈一个台阶,或者一次迈两个台阶,问上N级台阶,一共有几种方法。


恍惚之间让我想到我万恶的中学数学,这似乎是排列组合问题,于是我又重温了一遍组合公式。世界上一切知识都是用进废退的,哪怕我微积分学的再好,2年不用也是从头学起。幸好排列组合公式很简单,我又推导了一遍。


这问题可以这样看:通过确定迈2级台阶的数量,再排列组合他们的位置。以7级台阶为例,

0次的话,就是7步一级一级上台阶,只有1种可能;

1次的话,就是1一个2级,5个1级,共6步。就像一共有6个位置,选择一个放置迈2级台阶的元素,是C(6,1),就是从6个里面选出来1个的组合。有6种可能。

2次的话,就是2个2级,3个1级,共5步。就像一共有5个位置,选择两个放置迈2级台阶的元素,是C(5,2),就是5个里面选出来2个的组合,并且是元素之间是无序的。有10种可能。

3次的话,就是3个2级,1个1级,共4步。就像一共有4个位置,选择三个放置迈2级台阶的元素,是C(4,3),就是从4个里面选出来3个的组合。有4种可能。

4次,已经超过了7级台阶,结束。



从而,剩下的就是从0开始到最大的2级台阶出现次数,每种情况排列组合。

<span style="white-space:pre">	</span>double Fact(int n, double sum)
	{
		if (n <= 1)
		{
			return sum;
		}

		return Fact(n - 1, n * sum);
	}

	int CC(int m, int n)
	{
		double sum = 1;
		double d1 = Fact(n, sum);
		sum = 1;
		double d2 = Fact(m, sum);
		sum = 1;
		double d3 = Fact(n - m, sum);

		double d = d1 / d2 / d3;

		return d + 0.5;
	}

	int climbStairs(int n) {
		int count = n / 2;
		int ret = 0;;
		for (int i = 0; i <= count;i++)
		{
			int k = n - i * 2;
			int cc = CC(i, i + k);
			ret += cc;
		}

		return ret;
	}


原来上个楼梯都有这么多学问,看来计算机最后都是数学问题,虽然实际上并没啥用。


注意计算阶乘时候,13的阶乘已经超过int型的上限,double型计算有累计误差需要纠正一下。利用前面题目积累的函数,尾递归求阶乘。这个时候,才发现这个网站题目设计的科学性,就像教材一样循序渐进,如果我大学时候能遇到这样的网站多好,哎。不过遇到也没用,那个时候我连电脑都没有,就像现在有了驾照没有车开似的,看来有些事情是不能超前的。


完成A目标有B,C条件,你要完成A,先达到了B,然后不停等C,这样并不是好办法。优化算法是,先完成困难的C,再顺利的完成B,顺理成章完成A。分步骤解决问题是人生一大课题,不要太超前。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值