Home
  • 计算机网络
  • 操作系统
  • 数据结构与算法
  • 设计模式
  • JavaSE
  • JVM
  • JUC
  • Netty
  • CPP
  • QT
  • UE
  • Go
  • Gin
  • Gorm
  • HTML
  • CSS
  • JavaScript
  • vue2
  • TypeScript
  • vue3
  • react
  • Spring
  • SpringMVC
  • Mybatis
  • SpringBoot
  • SpringSecurity
  • SpringCloud
  • Mysql
  • Redis
  • 消息中间件
  • RPC
  • 分布式锁
  • 分布式事务
  • 个人博客
  • 弹幕视频平台
  • API网关
  • 售票系统
  • 消息推送平台
  • SaaS短链接系统
  • Linux
  • Docker
  • Git
GitHub (opens new window)
Home
  • 计算机网络
  • 操作系统
  • 数据结构与算法
  • 设计模式
  • JavaSE
  • JVM
  • JUC
  • Netty
  • CPP
  • QT
  • UE
  • Go
  • Gin
  • Gorm
  • HTML
  • CSS
  • JavaScript
  • vue2
  • TypeScript
  • vue3
  • react
  • Spring
  • SpringMVC
  • Mybatis
  • SpringBoot
  • SpringSecurity
  • SpringCloud
  • Mysql
  • Redis
  • 消息中间件
  • RPC
  • 分布式锁
  • 分布式事务
  • 个人博客
  • 弹幕视频平台
  • API网关
  • 售票系统
  • 消息推送平台
  • SaaS短链接系统
  • Linux
  • Docker
  • Git
GitHub (opens new window)
  • 哈希表

  • 双指针

  • 数组

  • 字符串

  • 链表

  • 树

  • 回溯

  • 动态规划

    • 典型问题—斐波那契类型
      • 70. 爬楼梯
      • 746. 使用最小花费爬楼梯
      • 198. 打家劫舍
    • 典型dp—背包问题
    • 典型dp—子序列问题
    • 典型dp—股票问题
    • 线性dp
    • 区间dp
    • 树形dp
    • 状压dp
    • 数位dp
    • 多维dp
  • 图

  • 二分查找

  • 贪心

  • 栈&队列

  • 堆

  • 位运算

  • 数据结构设计

  • rui的精选题单

  • 笔试真题

  • LeetCode周赛

  • ACM模式输入输出
  • 数学

  • 数据结构与算法
  • 动态规划
Nreal
2023-11-16
目录

典型问题—斐波那契类型

# 70. 爬楼梯 (opens new window)

状态定义:第 i 级台阶有dp[i]中方法;

转移方程:dp[i+1]=dp[i]+dp[i-1];

初始状态:dp[0]=1,dp[1]=1;

返回值:dp[n];

记忆化搜索:

class Solution {
    int[] memo;
    public int climbStairs(int n) {
        memo = new int[n+1];
        return dfs(n);
    }
    int dfs(int n){
        if(n<=2)
            return n;
        if(memo[n]>0)
            return memo[n];
        memo[n] = dfs(n-1)+dfs(n-2);
        return memo[n];
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

动态规划:

class Solution {
    public int climbStairs(int n) {
        int[] dp = new int[n+1];
        dp[0] = 1;
        dp[1] = 1;
        for (int i=2;i<=n;i++) {
            dp[i] = dp[i-1] + dp[i-2];
        }
        return dp[n];
    }
}
1
2
3
4
5
6
7
8
9
10
11

# 746. 使用最小花费爬楼梯 (opens new window)

状态定义:第 i 级台阶总花费;

状态转移:dp[i]=min(dp[i-1],dp[i-2])+cost[i];

初始状态:dp[0]=cost[0];dp[1]=min(cost[0]+cost[1],cost[1])=cost[1];

返回值:dp[n]=min(dp[n-1],dp[n-2]),到 n级台阶无花费;

记忆化搜索:

class Solution {
    int[] memo;
    int[] cost;
    public int minCostClimbingStairs(int[] cost) {
        this.cost = cost;
        int n = cost.length;
        memo = new int[n+1];
        return dfs(n);
    }
    int dfs(int i){
        if(i==0||i==1)
            return cost[i];
        if(memo[i]!=0)
            return memo[i];
        memo[i] = Math.min(dfs(i-1),dfs(i-2))+(i==cost.length?0:cost[i]);
        return memo[i];
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

动态规划:

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int n = cost.length;
        int[] dp = new int[n];
        dp[0] = cost[0];
        dp[1] = cost[1];
        for(int i=2;i<n;i++){
            dp[i] = Math.min(dp[i-2],dp[i-1])+cost[i];
        }
        return Math.min(dp[n-2],dp[n-1]);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

# 198. 打家劫舍 (opens new window)

状态定义:偷第 i 间房屋偷窃到的最高金额;

状态转移:dp[i] =max(dp[i-2]+nums[i],dp[i-1]);

初始状态:dp[0]=nums[0],dp[1]=max(nums[0],nums[1]);

返回值:dp[n-1];

记忆化搜索:

  1. 从后向前思路:n不选,为f(n-1);n选,则为f(n-2);

    class Solution {
        int[] memo;
        int[] nums;
        public int rob(int[] nums) {
            this.nums = nums;
            int n = nums.length;
            memo = new int[n];
            Arrays.fill(memo,-1);
            return dfs(n-1);
        }
        int dfs(int i){
            if(i<0) 
                return 0;
            if(memo[i]!=-1) 
                return memo[i];
            memo[i] = Math.max(dfs(i-1),dfs(i-2)+nums[i]);
            return memo[i];
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
  2. 从前向后思路:返回[i,...)抢到的最大值;

    class Solution {
        int[] memo;
        int[] nums;
        public int rob(int[] nums) {
            this.nums = nums;
            int n = nums.length;
            memo = new int[n];
            Arrays.fill(memo,-1);
            return dfs(0);
        }
        int dfs(int i){
            if(i>=nums.length) 
                return 0;
            if(memo[i]!=-1) 
                return memo[i];
            memo[i] = Math.max(dfs(i+1),dfs(i+2)+nums[i]);
            return memo[i];
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

动态规划:

class Solution {
    public int rob(int[] nums){
        int n = nums.length;
        if(n==1){
            return nums[0];
        }
        if(n==2){
            return Math.max(nums[0],nums[1]);
        }
        int[] dp = new int[n];
        dp[0] = nums[0];
        dp[1] = Math.max(nums[0],nums[1]);
        for(int i=2;i<nums.length;i++){
            dp[i] = Math.max(dp[i-1],dp[i-2]+nums[i]);
        }
        return dp[n-1];
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

如何规避转移方程下标为负的情况?

class Solution {
    public int rob(int[] nums) {
        int n = nums.length;
        int[] dp = new int[n+2];
        for(int i=0;i<n;i++){
            dp[i+2] = Math.max(dp[i+1],dp[i]+nums[i]);
        }
        return dp[n+1];
    }
}
1
2
3
4
5
6
7
8
9
10
遍历dfs
典型dp—背包问题

← 遍历dfs 典型dp—背包问题→

Theme by Vdoing | Copyright © 2021-2024
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式