IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 动态规划 学习笔记 -> 正文阅读

[数据结构与算法]动态规划 学习笔记

1.动态规划步骤

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

2. 一维dp数组做题记录

做题由简到难记录

入门/简单题

爬楼梯

在这里插入图片描述

(1)确定dp[i]含义

  • i表示阶梯层数
  • dp[i]表示到达阶梯i有多少种跳法

(2) 确定递推公式

  • dp[i] = dp[i-1]+dp[i-2]
    说明:因为对于阶梯i,其跳法=上一级跳一阶+上上一级跳两阶
    所以跳上阶梯i的跳法= 阶梯[i-1]+阶梯[i-2]

(3)初始化dp[i]
dp[0] = 0; //阶梯为0
dp[1] = 1; //阶梯为1 1种
dp[2] = 2; //阶梯为2 2种

(4)确定遍历顺序

此题遍历顺序比较简单,将1~N每级阶梯遍历一次即可

(5)举例推导

纸上画一下dp表对应比照一下

(6)写出代码

class Solution {
    public int climbStairs(int n) {
        if(n<=2)
            return n;
        int[] dp = new int[n];
        dp[0] = 0;
        dp[1] = 1;
        dp[2] = 2;
        for(int i=3;i<n;i++){
            dp[i] = dp[i-1]+dp[i-2];
        }
		//最后一个阶梯的结果=[n-1]+[n-2]
        return dp[n-1]+dp[n-2];
    }
}

使用最小花费爬楼梯

在这里插入图片描述
(1)确定dp[i]含义

  • i表示第i级阶梯
  • dp[i]表示到达第i级阶梯花费的最小体力值

(2)确定递推公式

dp[i] = Math.min(dp[i-1],dp[i-2])+cost[i]

说明:当前阶梯花费最少体力值= 能跳上该阶梯时的最少体力值+当前阶梯花费的体力值

(3)dp初始化

dp[0] = cost[0];
dp[1] = cost[1];

(4)确定遍历顺序

同样将所有阶梯遍历一遍

(5)举例推导dp数组

画图举例

(6)写代码

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        if(cost.length<=1)
            return cost[cost.length];
        int[] dp = new int[cost.length];
        dp[0] = cost[0];
        dp[1] = cost[1];
        for(int i=2;i<cost.length;i++){
            dp[i] = Math.min(dp[i-1],dp[i-2])+cost[i];
        }
        //最后可以从最后一个阶梯跳,或者倒数第二个阶梯跳上去
        return Math.min(dp[cost.length-1],dp[cost.length-2]);
    }
}

中等题

打家劫舍

在这里插入图片描述

(1)确定dp[i]的含义

  • i表示房间号
  • dp[i]表示偷到对应房间号为止,最大的金额

(2)确定推导公式

  • dp[i] = Math.max(dp[i-3]+dp[i-2])+nums[i]
    说明:因为要间隔,画图就明白,只有两种选择 i-2或i-3

(3)dp初始化
dp[0] = nums[0];
dp[1] = nums[1];
dp[2] = nums[0]+nums[2];

(4)确定遍历顺序

对每个房间遍历一次

(5)举例推导dp数组

画图得证

(6)写出代码

class Solution {
    public int rob(int[] nums) {
        if(nums.length==1){
            return nums[0];
        }
        if(nums.length==2){
            return Math.max(nums[0],nums[1]);
        }

        int[] dp = new int[nums.length];
        dp[0] = nums[0];
        dp[1] = nums[1];
        dp[2] = nums[0]+nums[2];

        for(int i=3;i<nums.length;i++){
            dp[i] = Math.max(dp[i-3],dp[i-2])+nums[i];
        }

        return Math.max(dp[nums.length-2],dp[nums.length-1]);
    }
}

打家劫舍 II

在这里插入图片描述

做法和打家劫舍1差不多。区别只是区分一下房间1选择和不选择的两种情况,分别计算值,取最大值作为结果

class Solution {
    public int rob(int[] nums) {
        int len = nums.length;
        if(len<=2){
            if(len==1)
                return nums[0];
            return Math.max(nums[0],nums[1]);
        }else if(len==3){
            if(nums[0]>nums[1]){
                return Math.max(nums[0],nums[2]);
            }else{
                return Math.max(nums[1],nums[2]);
            }
        }
        int[] dp = new int[nums.length];

        //第一种可能 房间1必偷 最后一个房间不偷
        dp[0] = nums[0];
        dp[1] = 0;
        dp[2] = nums[0]+nums[2];
        dp[3] = nums[0]+nums[3];
        for(int i=4;i<nums.length;i++){
            dp[i] = Math.max(dp[i-3],dp[i-2])+nums[i];
        }
        //拿倒数第三个房间和倒数第二个房间比较 取最大
        int max1 = Math.max(dp[nums.length-3],dp[nums.length-2]);

        //第二种可能 房间1不偷 最后一个房间必偷
        dp[0] = 0;
        dp[1] = nums[1];
        dp[2] = nums[2];
        dp[3] = nums[1]+nums[3];
        for(int i=4;i<nums.length;i++){
            dp[i] = Math.max(dp[i-3],dp[i-2])+nums[i];
        }
        //拿倒数第二个房间和倒数第一个房间比较 取最大
        int max2 = Math.max(dp[nums.length-2],dp[nums.length-1]);

        //返回房间1偷与不偷的最大选择值
        return Math.max(max1,max2);
    }
}

by ruoxi 8.4

删除并获得点数

在这里插入图片描述
提示:如果深刻理解了此题的做法,那么此题和打家劫舍的做法类似

首先,我们先明确一个概念,就是每个位置上的数字是可以在两种前结果之上进行选择的:

如果你不删除当前位置的数字,那么你得到就是前一个数字的位置的最优结果。
如果你觉得当前的位置数字i需要被删,那么你就会得到i - 2位置的那个最优结果加上当前位置的数字乘以个数。
以上两个结果,你每次取最大的,记录下来,然后答案就是最后那个数字了。

上述的每个位置上的数字,指的是像存储1,2,3,4,5这种自然数个数的数组

那么可以创建一个count[]数组,用于存储每个自然数在nums[]中出现的次数

count的长度=nums[]数组中的最大值(max)

比如nums[] = {1,1,2,3,3,3},那么count[]={0,2,1,3}
说明:0在nums中出现了0次 1出现了2次 2出现1次 3出现3次

(1)明确dp[i]的含义

  • i表示选择自然数i
  • dp[i]表示选择i后能得到的最大点数

这里的dp[i]长度也就等于count的长度,因为dp[i]是选择自然数i,count存储的是自然数i出现的次数

(2)找出递推公式

  • dp[i] = Math.max(dp[i-1],dp[i-2]+i*count[i])

(3)初始化dp
dp[0] = 0; //因为选择0,无论多少个0都是0
dp[1] = nums中1出现的次数*1

(4)确定遍历顺序

对count[]数组遍历一遍即可

(5)举例推导dp数组

画图举例得证

(6)写代码

class Solution {
    public int deleteAndEarn(int[] nums) {
        int len = nums.length;
        if(len==0)
            return 0;

        //获取nums数组的最大值
        int max = 0;
        for(int i=0;i<len;i++){
            if(nums[i]>max){
                max = nums[i];
            }
        }
        //创建count数组,存储每个数字值在nums[]中存在的个数
        int[] count = new int[max+1];
        //创建dp数组
        int[] dp = new int[max+1];

        //num数字值也就对应count数组的下标
        //顺带初始化dp
        for(int num : nums){
            count[num] ++;
            if(num==1){
                dp[1] +=1;
            }
        }
        dp[0] = 0;

        if(max==1){
            return dp[1];
        }

        //递推方向 :dp[i] = Math.max(dp[i-1],dp[i-2]+count[i]*i)
        for(int i=2;i<max+1;i++){
            dp[i] = Math.max(dp[i-1],dp[i-2]+count[i]*i);
        }

        return Math.max(dp[max],dp[max-1]);
    }
}

持续更新中…

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-08-05 17:36:08  更:2021-08-05 17:39:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 18:37:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码