代码随想录第38天|509. 斐波那契数,70. 爬楼梯,746. 使用最小花费爬楼梯,动态规划开始啦!!

动态规划理论基础

所以动态规划中每一个状态一定是由上一个状态推导出来的,这一点就区分于贪心,贪心没有状态推导,而是从局部直接选最优的.

对于动态规划问题,我将拆解为如下五步曲,这五步都搞清楚了,才能说把动态规划真的掌握了!

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

一些同学可能想为什么要先确定递推公式,然后在考虑初始化呢?

因为一些情况是递推公式决定了dp数组要如何初始化!

做动规的题目,写代码之前一定要把状态转移在dp数组的上具体情况模拟一遍,心中有数,确定最后推出的是想要的结果

然后再写代码,如果代码没通过就打印dp数组,看看是不是和自己预先推导的哪里不一样。

如果打印出来和自己预先模拟推导是一样的,那么就是自己的递归公式、初始化或者遍历顺序有问题了。

如果和自己预先模拟推导的不一样,那么就是代码实现细节有问题。

这样才是一个完整的思考过程,而不是一旦代码出问题,就毫无头绪的东改改西改改,最后过不了,或者说是稀里糊涂的过了

509. 斐波那契数

代码实现

class Solution {
    public int fib(int n) {
        int[] dp=new int[n+1];
        if(n<=1){return n;}
        dp[0]=0;
        dp[1]=1;
        
        for(int i=2;i<=n;i++){
            dp[i]=dp[i-1]+dp[i-2];
        }
        return dp[n];
     
    }
}

70. 爬楼梯

代码实现

dp[n]只能是在dp[n-1]基础上走一个台阶,或者在dp[n-2]基础上走两个台阶

class Solution {
    public int climbStairs(int n) {
        int[] dp=new int[n+1];//dp[n]指的是到达台阶n有几种方案
        //初始化
        dp[0]=1;
        dp[1]=1;
        for(int i=2;i<=n;i++){
            dp[i]=dp[i-1]+dp[i-2];
        }
        return dp[n];
    }
}

746. 使用最小花费爬楼梯

这道题我的递推公式理解错误了,初始版本同时产生cost[i[数组溢出的问题

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        //dp[i]表示到达台阶i花费了多少钱
        int[] dp=new int[cost.length+1];
        dp[0]=cost[0];
        dp[1]=cost[1];
        for(int i=2;i

重新审题:

跳到 下标 0 或者 下标 1 是不花费体力的, 从 下标 0 下标1 开始跳就要花费体力了。

dp[i]的定义:到达第i台阶所花费的最少体力为dp[i]

可以有两个途径得到dp[i],一个是dp[i-1] 一个是dp[i-2]

dp[i - 1] 跳到 dp[i] 需要花费 dp[i - 1] + cost[i - 1]。

dp[i - 2] 跳到 dp[i] 需要花费 dp[i - 2] + cost[i - 2]。

代码实现

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        //dp[i]表示到达台阶i花费了多少钱
        int[] dp=new int[cost.length+1];
        //初始化为0是因为题目给出从1,2台阶开始跳,那么从1,2台阶开始
        dp[0]=0;
        dp[1]=0;
        for(int i=2;i

你可能感兴趣的:(算法训练营,java)