70. Climbing Stairs---组合C(m,n)的使用,注意int溢出!

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?

Note: Given n will be a positive integer.

Example 1:

Input: 2
Output: 2
Explanation: There are two ways to climb to the top.

  1. 1 step + 1 step
  2. 2 steps

Example 2:

Input: 3
Output: 3
Explanation: There are three ways to climb to the top.

  1. 1 step + 1 step + 1 step
  2. 1 step + 2 steps
  3. 2 steps + 1 step

思路,通过分析前几个数,我们可以使用讨论里说的斐波那契法,即第n个数=n-1个数+n-2个数
我的思路是采用排列组合的形式,通过分析,可以发现对于n个台阶,我们可以采用1个两步,2个两步。。。n/2个两步的组合,并且针对不同两步组合m,其变化形式有C(m,n-m)种组合。则总的方法可以有C(0,n)+C(1,n-1)+C(2,n-2)+…+C(n/2, n-n/2).因此,要首先设计组合的求取方法combination。具体算法如下:

class Solution {
    public int climbStairs(int n) {
        int numOf2 = n/2;
        int sum = 0;
        for(int m = 0; m <= numOf2; m++){
            sum += combination(m, n-m);
        }
        return sum;
    }
    public long combination(int m, int n){
        long c = 1;    //注意用long
        if(m > n)
            return -1;
        if(m > n-m)
            m = n-m;
        for(int i = 1; i <= m; i++){
            c = c*(n+1-i)/i;
        }
        return c;
    }
}

在该算法中要注意的是对于大数乘法,要采用长整形,否则会溢出,关于溢出的知识点可以看看java int溢出总结
摘取部分如下:
java 类型提升

int型整数相乘并不会进行类型提升(type promotion),在widening conversion(JSL 5.1.2)写到:

If any of the operands is of a reference type, unboxing conversion(JSL 5.1.8) is performed. Then:
If either operand is of type double, the other is converted to double.
Otherwise, if either operand is of type float, the other is converted to float.
Otherwise, if either operand is of type long, the other is converted to long.
Otherwise, both operands are converted to type int.

所以下述语句并不会发生溢出:

byte a = 40;
byte b = 50;
byte c = 100;
int d = a * b / c;

虽然40 50 = 2000已经超过了byte的范围,但是java compile在计算a b之前已经都将它们转换成了int类型了,所以并不会有编译问题。

猜你喜欢

转载自blog.csdn.net/timemagician/article/details/79545464