LeetCode刷题day38|509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯

一、509. 斐波那契数

递推公式已经给出,所以比较简单。注意一下数组的初始化就可以了。
以下是代码部分:

public class 斐波那契数509 {

    //递归方法 ——可通过,时间有点长
    public int fib(int n) {

        if( n == 0)
            return 0;
        if( n ==1 )
            return 1;

        return fib(n-1) + fib(n-2);
    }

    // 动态规划
    public int fib2(int n) {

        //踩坑,没有判断n=0或1,导致数组越界
        if( n == 0)
            return 0;
        if( n ==1)
            return 1;

        //1. 确定dp数组,fib(i)。注意,这里大小是 n+1
        int[] dp = new int[n+1];

        //2. 确定递推公式
        //dp[i] = dp[i-1] + dp[i-2]

        //3. 初始化dp数组
        dp[0] = 0;
        dp[1] = 1;

        //4. 确定遍历顺序
        for (int i = 2; i < dp.length; i++) {
            dp[i] = dp[i-1] + dp[i-2];
        }

        return dp[n];
    }
}

二、70. 爬楼梯

这道题主要理解递推公式的思想:

爬第n阶楼梯的方法数量,等于 2 部分之和——

  1. 爬上 n-1n−1 阶楼梯的方法数量。因为再爬1阶就能到第n阶
  2. 爬上 n-2n−2 阶楼梯的方法数量,因为再爬2阶就能到第n阶

其实,你会发现递推公式的形式跟斐波那契数一样,唯一需要注意的点是在初始化的时候dp[0] = 1。(这里dp[0]=1其实是没有意义的,所以可以把初始化改为dp[1]=1,dp[2]=2。这样的话就是有意义的)

以下是代码部分:

public class 爬楼梯70 {

    @Test
    public void test(){
        climbStairs(8);
    }

    public int climbStairs(int n) {

        //1.确定dp数组
        int[] dp = new int[n+1];

        //2.递推公式
        // dp[i] = dp[i-1] + (i/2+1)

        //3.初始化
        //与斐波那契数列的唯一区别:dp[0] = 1
        dp[0] = 1;
        dp[1] = 1;

        //4.遍历顺序
        for (int i = 2; i < dp.length; i++) {
            dp[i] = dp[i-1] + dp[i-2];
        }

        return dp[n];
    }
}

三、746. 使用最小花费爬楼梯

这道题困扰了我很久,核心在于理解:

  1. 到达第i个台阶顶部所需要的最小费用
  2. 踏上第i个台阶所需要的最小费用

所谓到达,就是到了第i个台阶的顶部(即第i+1个台阶),此时是不需要必须踩第i个台阶的;而踏上第i个台阶,则是要踩在第i个台阶的,所以一定要加cost[i]。

1. 到达第i个台阶顶部

思路:若要到达第i个台阶顶部(即到第i+1个台阶),有两种方案:

  1. 从 i-1 阶走两步(dp[i-2] + cost[i-1] )
  2. 从 i 阶走一步(dp[i-1] + cost[i])

这里为什么是dp[i-2] + cost[i-1]。首先dp[i-2]指到达第i-2个台阶顶部(第i-1个台阶)之前所需要的最小花费,到了i-2顶部,想要到i顶部,要走两步,所以要踩第i-1台阶,花费为cost[i-1]。
以下是代码部分:

	public int minCostClimbingStairs2(int[] cost) {

        //到达第i个台阶顶部所需要的最小费用
        int[] dp = new int[cost.length];

        dp[0] = 0;
        dp[1] = Math.min(cost[0], cost[1]);

        for (int i = 2; i < dp.length; i++) {
            dp[i] = Math.min(dp[i-2]+cost[i-1], dp[i-1]+cost[i]);
        }

        return dp[dp.length-1];
    }

2. 踏上第i个台阶

思路:若要踏上第i个台阶,则也有两种方案:

  1. 从 i-2 阶走两步(dp[i-2] + cost[i] )
  2. 从 i-1 阶走一步(dp[i-1] + cost[i] )

以下是代码部分:

	public int minCostClimbingStairs(int[] cost) {

        //踏上第i个台阶所需要的最小费用
        //确定dp数组。如果有length+1个台阶的最小费用
        int[] dp = new int[cost.length];

        //递推公式
        //dp[i] += min(cost[i-1] ,cost[i-2]

        //初始化dp
        dp[0] = cost[0];
        dp[1] = cost[1];

        //遍历
        for (int i = 2; i < dp.length; i++) {
            //两种情况,从i-1不走i。从i-2走i
            dp[i] += Math.min(dp[i-1] , dp[i-2] + cost[i]);
        }

        return dp[dp.length-1];
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值