剑指offer编程题解法汇总8-跳台阶

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。

 

解题思路:

这其实是一个斐波那契数列,可以用递归的方式来接替。

F(n)=F(n-1)+F(n-2)   F(n-1)等于青蛙跳了1个台阶之后剩余的可能,F(n-2)等于青蛙跳了2个台阶之后剩余的可能。

当然,递归运算运算的次数指数型增长,当N比较大时,有可能会导致stackoverflow。

所以这里暂且换一种思路。

架设N=6,则分为4种可能性,跳2级的次数分别为0,1,2,3。然后

0:1种可能

1:5种可能

2:6种可能

3:1种可能

最终求和就得到13。

每种可能,其实可以理解为n个白球,m个黑球,有多少种排列组合。k=m+n,n>m,如下图:

public static void main(String[] args) {

        Solution solution = new Solution();
        int fibonacci = solution.JumpFloor(29);
        System.out.println(fibonacci);
    }

    public int JumpFloor(int target) {
        if (target == 1) {
            return 1;
        }
        int count = 0;
        int num1 = 0;
        for (int num2 = 0; num2 * 2 <= target; num2++) {
            num1 = target - num2 * 2;
            long num = getNum(num1, num2);
            count += num;
        }
        return count;
    }

    //num1个黑球,num2个白球,有多少种排列组合 架设num1+num2=num,共有(A num num)/(A num1 num1)/(A num2 num2)种可能
    public long getNum(int num1, int num2) {
        long count = 1;
        int num = num1 + num2;
        if (num1 == 0 || num2 == 0) {
            return count;
        }
        if (num1 > num2) {
            while (num > num1) {
                count = count * num;
                num--;
            }
            while (num2 > 1) {
                count = count / num2;
                num2--;
            }

        } else {
            while (num > num2) {
                count = count * num;
                num--;
            }
            while (num1 > 1) {
                count = count / num1;
                num1--;
            }

        }
        if (count < 0) {
            System.out.println("num1:" + num1);
        }
        return count;
    }

当然,这里存在一个问题,就是如果N过大的话,会导致long型也会溢出。所以这种解法也不是最好的,后续在想。

 

第二种解法,递归。其实就是我上面说的那种,但是我们可以换个思路,把结果缓存下来,那么就不需要多次运算了。也解决stackoverflow的问题。

代码如下:

import java.util.HashMap;
public class Solution {

    HashMap<Integer, Integer> cache = new HashMap<>();

    public static void main(String[] args) {
        Solution solution = new Solution();
        int i = solution.JumpFloor(4);
        System.out.println(i);
    }


    public int JumpFloor(int target) {
        if (target == 0) {
            return 0;
        }

        Integer cacheInt = cache.get(target);
        if (cacheInt != null) {
            return cacheInt;
        }
        if (target == 1) {
            return 1;
        }
        if (target == 2) {
            return 1;
        }
        int i1 = JumpFloor(target - 1);
        int i2 = JumpFloor(target - 2);
        int count = i1 + i2;
        cache.put(target, count);
        return count;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

失落夏天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值