【LeetCode】《LeetCode 101》第七章:动态规划

news2024/11/16 19:48:37

文章目录

  • 7.1 算法解释
  • 7.2 基本动态规划:一维
    • 70. 爬楼梯(简单)
    • 198.打家劫舍(中等)
    • 413. 等差数列划分(中等)
  • 7.3 基本动态规划:二维
    • 64. 最小路径和(中等)
    • 542. 01 矩阵(中等)
    • 221.最大正方形(中等)
  • 7.4 分割类型题
    • 279. 完全平方数(中等)
    • 91. 解码方法(中等)
    • 139. 单词拆分(中等)
  • 7.5 子序列问题
    • 300. 最长递增子序列(中等)
    • 1143. 最长公共子序列(中等)
  • 7.6 背包问题
    • 416. 分割等和子集(中等)
    • 474. 一和零(中等)
    • 322. 零钱兑换(中等)
  • 7.7 字符串编辑
    • 72. 编辑距离(困难)
    • 650. 只有两个键的键盘(中等)
    • 10. 正则表达式匹配(困难)
  • 7.8 股票交易
    • 121. 买卖股票的最佳时机(简单)
    • 188. 买卖股票的最佳时机 IV(困难)
    • 309.最佳买卖股票时机含冷冻期(中等)
  • 7.9 练习
    • 213. 打家劫舍 II(中等)
    • 53. 最大子数组和(中等)
    • 343. 整数拆分(中等)
    • 583. 两个字符串的删除操作(中等)
    • 646. 最长数对链(中等)
    • 376. 摆动序列(中等)
    • 494. 目标和(中等)
    • 714. 买卖股票的最佳时机含手续费(中等)
  • 总结

7.1 算法解释

动态规划 解决有很多重叠子问题 的情况的最优解时有效,它将问题重新组合成子问题。为了防止多次解决子问题,它们的结果都逐渐被计算并保存,从简单的问题直到整个问题都被解决。因此,动态规划保存递归时的结果,不会在解决同样问题的时候浪费时间。

动态规划只能应用于有最优子结构的问题,最优子结构指的是局部最优解能决定全局最优解(对有些问题这个要求并不能完全满足,因此有时需要引入一定的近似)。

解决动态规划问题的关键是找到状态转移方程,可以通过计算和存储子问题的解来求解最终问题。

同时,也可以对动态规划进行空间压缩,起到节省空间消耗的效果。

在一些情况下,动态规划可以看作是带有状态记录的优先搜索,如果一个子问题在优先搜索时已经计算过一次,可以把它的结果存储下来,之后遍历到该子问题的时候可以直接返回存储的结果。动态规划是自下而上的,即先解决子问题,再解决父问题;而带有状态记录的优先搜索是自上而下的,即从父问题搜索到子问题,若重复搜索到同一个子问题则进行状态记录,防止重复计算。如果题目需求的是最终状态,那么使用动态搜索比较方便;如果题目需要输出所有的路径,那么使用带有状态记录的优先搜索比较方便。

7.2 基本动态规划:一维

70. 爬楼梯(简单)

在这里插入图片描述在这里插入图片描述

思路及代码: 70. 爬楼梯

198.打家劫舍(中等)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码: 198.打家劫舍

413. 等差数列划分(中等)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码: 413. 等差数列划分

7.3 基本动态规划:二维

64. 最小路径和(中等)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码: 64. 最小路径和

542. 01 矩阵(中等)

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码: 542. 01 矩阵

221.最大正方形(中等)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码: 221.最大正方形

7.4 分割类型题

279. 完全平方数(中等)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码: 279. 完全平方数

91. 解码方法(中等)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码: 91. 解码方法

139. 单词拆分(中等)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码: 139. 单词拆分

7.5 子序列问题

300. 最长递增子序列(中等)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码: 300. 最长递增子序列

1143. 最长公共子序列(中等)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码: 1143. 最长公共子序列

7.6 背包问题

背包问题是一种组合优化的 NP 完全问题:有 N 个物品和容量为 W 的背包,每个物品都有自己的体积 w 和价值 v ,求拿哪些物品可以使背包所装下物品的总价值最大。

如果限定每种物品只能选择 0 个或 1 个,则此问题称为 0-1背包问题;如果不限定每种物品的数量,则称为无边界背包问题完全背包问题

  1. 使用动态规划解决背包问题,以 0-1 背包问题为例,定义二维数组 dp存储最大价值,其中 dp[i][j] 表示前 i 件物品体积不超过 j 的情况下能达到的最大价值。在遍历到第 i 件物品时,在当前背包总容量为 j 的情况下,如果我们不将物品 i 放入背包,那么 dp[i][j] = d[i-1][j] ,即前 i 个物品的最大价值等于只取前 i-1 个物品时的最大价值;如果将物品 i 放入,假设第 i 件物品体积为 w ,价值为 v ,那么得到 dp[i][j] = dp[i-1][j-w] + v 。我们只需要在遍历过程中对两种情况取最大值即可,总时间复杂度和空间复杂度都为 O(NW)。

        int knapsack(vector<int> weights, vector<int> values, int N, int W){
            vector<vector<int>> dp(N+1, vector<int>(W+1, 0));
            for(int i=1; i<=N; ++i){
                int w = weights[i-1], v = values[i-1];
                for(int j=1; j<=W; ++j){
                    if(j >= w){
                        // 当前背包容量>=w
                        dp[i][j] = max(dp[i-1][j], dp[i-1][j-w] + v);
                    }
                    else{
                        dp[i][j] = dp[i-1][j];
                    }
                }
            }
            return dp[N][W];
        }
    
  2. 可以进一步对 0-1背包进行空间优化, 将空间复杂度降为 O(W)。如图,假设目前考虑物品 i = 2, 它的体积 w = 2, 价值 v = 3;对于背包容量 j,我们可以得到 dp[2][j] = max(dp[1][j], dp[1][j-2] + 3) 。不难发现,永远只依赖于上一排 i = 1 的信息,之前算过的其他物品都不需要再使用。因此我们可以去掉 dp 矩阵的第一个维度,在考虑物品 i 时,变成 dp[j] = max(dp[j], dp[j-w] + v) 。需要注意,在遍历每一行的时候都需要逆向遍历 ,这样才能调用上一行物品 i-1 时 dp[j-w] 的值 ;如果按照从左到右的正序遍历,则 dp[j-w] 的值在遍历到 j 之前就已经被更新成物品 i 的值了。

    在这里插入图片描述

        int knapsack(vector<int> weights, vector<int> values, int N, int W){
            vector<int> dp(W+1, 0);
            for(int i=1; i<=N; ++i){
                int w = weights[i-1], v = values[i-1];
                for(int j=W; j>=w; --j){
                    dp[j] = max(dp[j], dp[j-w] + v);
                }
            }
            return dp[W];
        }
    
  3. 完全背包问题中,一个物品可以拿多次。如图所示,假设我们遍历到物品 i=2 时,且其体积为 w=2, 价值为 v=3;对于背包容量 j=5,最多只能装下两个该物品。那么状态转移方程就变成 dp[2][5] = max(dp[1][5], dp[1][3] + 3, dp[1][1] + 6) ,如果采用这种方法,假设背包容量无穷大,而物品大小无穷小,那么比较次数也会趋近于无穷大,远远超过 O(NW) 的比较次数。

    在这里插入图片描述

    怎么解决这个问题呢?不难发现,在 dp[2][3] 的时候,我们其实已经考虑了 dp[1][3] 和 dp[2][1] 的情况,而 dp[2][1] 也已经考虑了 dp[1][1] 的情况。因此,如下图所示,对于拿多个物品的情况,只需要考虑 dp[2][3] 即可,即 dp[2][5] = max(dp[1][5], dp[2][3] +3) 。这样,我们就得到了完全背包问题的状态转移方程:dp[i][j] = max(dp[i-1][j], dp[i][j-w] + v) ,和 0-1背包问题不同的是,第二个 i-1 替换成 i 。

    在这里插入图片描述

        int knapsack(vector<int> weights, vector<int> values, int N, int W){
            vector<vector<int>> dp(N+1, vector<int>(W+1, 0));
            for(int i=1; i<=N; ++i){
                int w = weights[i-1], v = values[i-1];
                for(int j=1; j<=W; +j){
                    if(j>=w)    dp[i][j] = max(dp[i-1][j], dp[i][j-w] + v);
                    else dp[i][j] = dp[i-1][j];
                }
            }
            return dp[N][W];
        }
    

    同样地,可以利用 空间压缩将时间复杂度降低为 O(W)。需要注意,遍历的时候需要 正向遍历 ,因为我们需要利用当前物品在 第 j-w 列的信息。

        int knapsack(vector<int> weights, vector<int> values, int N, int W){
            vector<int> dp(W+1, 0);
            for(int i=1; i<=N; ++i){
                int w = weights[i-1], v = values[i-1];
                for(int j=w; j<=W; +j){
                    if(j>=w)    dp[j] = max(dp[j], dp[j-w] + v);
                    else dp[j] = dp[j];
                }
            }
            return dp[W];
        }
    
  4. 在思考空间压缩前,先画出状态转移方程,方便思考如何进行空间压缩。此外,有一个简单的口诀:「0-1背包对物品的迭代放在外面,里面的体积或价值逆向遍历;完全背包对物品的迭代放在里层,外层的体积或价值正向遍历」。

416. 分割等和子集(中等)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码: 分割等和子集

474. 一和零(中等)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码: 一和零

322. 零钱兑换(中等)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码:零钱兑换

7.7 字符串编辑

72. 编辑距离(困难)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码: 编辑距离

650. 只有两个键的键盘(中等)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码: 只有两个键的键盘

10. 正则表达式匹配(困难)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码: 正则表达式匹配

7.8 股票交易

股票交易类问题通常使用动态规划解决,对于稍微复杂的股票交易类问题,比如需要冷却时间交易费用,则可以通过动态规划实现的状态机解决。

121. 买卖股票的最佳时机(简单)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码:买卖股票的最佳时机

188. 买卖股票的最佳时机 IV(困难)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码:188. 买卖股票的最佳时机 IV

309.最佳买卖股票时机含冷冻期(中等)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码: 309.最佳买卖股票时机含冷冻期

7.9 练习

213. 打家劫舍 II(中等)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码: 213. 打家劫舍 II

53. 最大子数组和(中等)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

思路及代码:53. 最大子数组和

343. 整数拆分(中等)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码: 343. 整数拆分

583. 两个字符串的删除操作(中等)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码: 583. 两个字符串的删除操作

646. 最长数对链(中等)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码: 646. 最长数对链

376. 摆动序列(中等)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码: 376.摆动序列

494. 目标和(中等)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路及代码: 494. 目标和

714. 买卖股票的最佳时机含手续费(中等)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

思路及代码: 714. 买卖股票的最佳时机含手续费

总结

  1. 其实做下来,发现动态规划的思考过程都是一样的,分为四个步骤:

    • 状态定义;
    • 确定状态转移方程;
    • 初始化的考虑;
    • 确定最终的返回结果。
  2. 题目分类:

    • 基本动态规划:一维、二维」:都比较简单,当前状态一般只需要考虑上一个状态,基本上很容易进行空间压缩;

    • 分割类型题」:需要确定分隔位置,因此状态转移方程比较复杂,有时候需要考虑每一种情况;

    • 子序列问题」:子序列不要求连续,但如果是子数组或子字符串必须连续。对于子序列问题,有两种动态规划方法:

      • 第一种动态规划方法:定义 dp 数组,其中 dp[i] 表示以 i 结尾的子序列的性质。在处理好每个位置后,统计一遍各个位置的结果即可得到题目要求的结果。
      • 第二种动态规划方法:「定义一个 dp 数组,其中 dp[i]表示到位置 i 为止的子序列性质,并不是必须以 i 结尾」,此时 dp 数组的最后一位即为题目所求,不需要对每个位置进行统计。
    • 背包问题」:背包问题又分为 0-1 背包问题完全背包问题,一般定义二维数组 dp 存储最大价值,其中 dp[i][j] 表示前 i 件物品体积不超过 j 的情况下能达到的最大价值

      对于背包问题,空间压缩比较复杂。在思考空间压缩前,先画出状态转移方程,方便思考如何进行空间压缩。此外,有一个简单的口诀:「0-1背包对物品的迭代放在外面,里面的体积或价值逆向遍历;完全背包对物品的迭代放在里层,外层的体积或价值正向遍历」。

    • 字符串编辑问题」:这类问题一般会对两个字符进行比较,因此定义 dp[i][j] 表示第一个字符串到 i ,第二个字符串到 j 的性质。然后思考 str[i] 和 str[j] 之间的关系,可能需要对每种情况进行分析。

    • 股票交易问题」:这类问题如果建立状态机就很容易得出答案。一般分为 持有不持有 股票两种情况进行讨论,定义 buy 和 sell 两个一维数组,分别表示买入(持有)和卖出(不持有)股票时候的最大收益。由于状态一般只和前一天的状态有关系,所以也很容易就进行空间压缩。对于初始化需要仔细考虑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/497889.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【项目经理】论项目经理的自我修养

项目经理的非职权领导力 文章目录 项目经理的非职权领导力一、权利的类型二、构成权利的三要素三、沟通是实施影响力的重要手段3.1 沟通的主要类型3.2 沟通的内容和形式3.3 沟通的主要困难 四、综合沟通协调的技巧4.1 常见的负面反馈4.2 沟通技巧 五、论项目经理的自我修养5.1 …

PyCharm2023.1下载、安装、注册以及简单使用【全过程讲解】

在使用PyCharm IDE之前&#xff0c;请确保自己的计算机里面安装了Python解释器环境&#xff0c;若没有下载和安装可以看看我之前的文章>>>Python环境设置>>>或者还可以观看视频讲解。 注意&#xff1a;本文软件的配置方式仅供个人学习使用&#xff0c;如有侵…

如何将PDF文件转换为Excel表格?这两个方法方便实用!

如何将PDF文件转换为Excel表格&#xff1f; 很多人在编辑和处理表格内容时&#xff0c;需要将PDF文件转换为Excel表格&#xff0c;以更好地修改和排版。虽然PDF文件往往起到展示整体效果的作用&#xff0c;但是PDF转Excel也是办公中老生常谈的文档处理操作。如果您还不知道如何…

Java架构中VO、DTO、DO、BO的区别与联系(超详解)

VO、DTO、DO、BO的区别与联系 前言一、概念1、VO (View Object)2、DTO(Data Transfer Object)3、DO(Data Object)4、BO&#xff08;Business Object&#xff09; 二、为什么会存在Vo&#xff1f;三、总结 前言 本博主将用CSDN记录软件开发求学之路上亲身所得与所学的心得与知识…

深入理解 node 中的文件流

为什么要使用文件流 想象这样一个场景&#xff0c;我要处理一个 10G 的文件&#xff0c;但我的内存大小只有 2G&#xff0c;该怎么办&#xff1f; 我们可以分 5 次读取文件&#xff0c;每次只读取 2G 的数据&#xff0c;这样就可以解决这个问题&#xff0c;那么这个分段读取的过…

HTML基本标签介绍

HTML的基本认识&#xff01; 文章目录 HTML基本标签介绍1. HTML是什么&#xff1f;1.1 HTML代码的样子1.2 HTML文件的展示1.3 VSCode配置 2. HTML常用标签介绍2.1 注释标签2.2 标题标签2.3 段落标签2.4 换行标签2.5 格式化标签2.6 图片标签2.7 超链接标签2.8 表格标签2.9 列表标…

Windows下 ffmpeg 的 “Protocol not found“ 的解决

文章目录 1. 问题描述2. 排查方法记录2.1 检查代码中编码器是否安装2.2 确定ffmpeg版本号2.3 打印编译参数2.4 查看运行中调用dll 1. 问题描述 调用ffmpeg库中&#xff0c;如果使用 avformat_open_input 打开返回 -1330794744,使用 av_strerror char buf[1024]{0};int result …

JavaScript高阶项目—组件化的可编辑表格

1. 任务要求 JSON数据,表格中数据来自服务端&#xff0c;由JSON格式表示。通过JSON数据生成可编辑表格&#xff0c;并且灵活配置可编辑得到数据列。输入数据时打开开发者模式有提示&#xff0c;并且设置判断&#xff0c;要求输入正确的成绩。要求表格的可编辑列&#xff0c;计…

新鲜热乎的春招面经汇总

作者&#xff1a;阿秀 校招八股文学习网站&#xff1a;https://interviewguide.cn 这是阿秀的第「263」篇原创 小伙伴们大家好&#xff0c;我是阿秀。 欢迎今年参加秋招的小伙伴加入阿秀的学习圈&#xff0c;目前已经超过 2300 小伙伴加入&#xff01;去年认真准备和走下来的基…

高精度DEM(12.5m)数据以及下载方式介绍

一、 DEM代表数字高程模型&#xff0c;是一种数字地形模型&#xff0c;用于表示地球表面的海拔高度。 DEM数据可以通过多种方法获得&#xff0c;包括激光雷达、遥感技术和GPS测量等。 DEM数据通常以栅格形式呈现&#xff0c;每个栅格单元包含一个高度值。DEM数据可以用于许多…

gitee如何上传自己的代码

1&#xff0c;右击你要上传的项目&#xff0c;选择Git bash Here 2,接着输入 git init 此时你会发现你的当前文件夹会多了一个.git文件夹 点击.git文件夹&#xff0c;进入之后发现是这样&#xff0c;然后用记事本打开config文件 3,发现是这样&#xff0c;然后我们要配置一个用…

简单科普视频云

1. 本文目的 每当我连写几篇行业分析的虚文以后&#xff0c;我都会做一两篇技术科普和产品分析的硬核分享&#xff0c;证明我是脚踏实地的戏说江姗&#xff0c;而非云里雾里的胡乱推倒。 其实是写硬核分享应者寥寥&#xff0c;反倒是写一些虚文很多人看热闹。 最近看到PPIO王闻…

数字化转型导师坚鹏:如何制定企业数字化转型年度培训规划

如何制定企业数字化转型年度培训规划 ——以推动企业数字化转型战略落地为核心&#xff0c;实现知行果合一 课程背景&#xff1a; 很多企业都在开展企业数字化转型培训工作&#xff0c;目前存在以下问题急需解决&#xff1a; 缺少针对性的企业数字化转型年度培训规划 不清…

双目视觉(七)稀疏双目匹配

系列文章 双目视觉&#xff08;一&#xff09;双目视觉系统双目视觉&#xff08;二&#xff09;双目匹配的困难和评判标准双目视觉&#xff08;三&#xff09;立体匹配算法双目视觉&#xff08;四&#xff09;匹配代价双目视觉&#xff08;五&#xff09;立体匹配算法之动态规…

测试1:概念

1.需求 用户需求:该需求一般比较简略。(一句话) 软件需求:或者功能需求,详细描述开发人员必须实现的软件功能(一个文档) 2.BUG 说明是存在的并且正确,程序和规格说明之间不匹配是错误 3.软件生命周期 从诞生到停服 需求分析,计划,设计,编码,测试,运行维护 需求分析:分析…

出海的中国企业,为什么有80%都选择了这家云服务商?

对于想要出海的中国企业来说&#xff0c;什么样的云服务才是他们的最佳选择&#xff1f; 中国企业出海驶入快车道 中国企业的出海大潮&#xff0c;多年来一直方兴未艾&#xff0c;并且得到了政府部门的大力支持。这股“走出去”的热潮&#xff0c;一方面对内有利于推动产业升级…

均摊时间复杂度

均摊时间复杂度&#xff0c;它对应的分析方法&#xff0c;摊还分析&#xff08;或者叫平摊分析&#xff09; 均摊时间复杂度应用的场景比它更加特殊、更加有限 // array表示一个长度为n的数组// 代码中的array.length就等于nint[] array new int[n];int count 0;void insert…

电子时钟实现

访问【WRITE-BUG数字空间】_[内附完整源码和文档] 利用汇编语言实现一个可以在显示器上显示时、分、秒的电子时钟&#xff0c;并能提供设置闹钟时间、选择闹钟铃声功能。 问题描述 利用汇编语言实现一个可以在显示器上显示时、分、秒的电子时钟&#xff0c;并能提供设置闹钟时间…

【Go编程语言】 Go和Goland的安装

Go和Goland的安装 文章目录 Go和Goland的安装一、 Goland官网二、打开Goland&#xff0c;并输入激活码 GO官网地址&#xff1a;https://golang.google.cn/ go中文网地址&#xff1a;https://studygolang.com/dl 安装完成得到的目录 环境变量配置&#xff1a; 1.新建变量 变…

【Gin框架深度解析】路由实现原理,让你彻底掌握Gin中路由的奥秘!

文章目录 Gin路由1、基本路由2、Restful风格的API3、API参数4、URL参数5、表单参数6、上传单个文件6.1、上传特定文件 7、上传多个文件8、路由分组9、404页面处理10、路由原理 Gin路由 1、基本路由 ​ 举一个例子&#xff1a; package mainimport ("net/http"&quo…