2023-05-04 线性DP_力扣练习

news2024/11/23 11:38:50

线性DP的力扣题目练习

这一章将会介绍线性动态规划的相关概念和经典问题,并给出一些练习题供大家演练。

用动态规划解决问题的过程有以下几个关键点:状态定义,状态的转移,初始化和边界条件。

状态定义 就是定义子问题,如何表示目标规模的问题和更小规模的问题。例如常见的方法:定义状态 dp[n],表示规模为 nn 的问题的解,dp[n - 1] 就表示规模为 n - 1n−1 的子问题的解。在实战中 dp[n] 的具体含义需要首先整理清楚再往下做。

状态转移 就是子问题之间的关系,例如定义好状态 dp[n],此时子问题是 dp[n-1] 等,并且大规模的问题的解依赖小规模问题的解,此时需要知道怎样通过小规模问题的解推出大规模问题的解。这一步就是列状态转移方程的过程。一般的状态转移方程可以写成如下形式

dp[n] = f(dp[i]) 其中 i < n

按照状态定义和状态转移的常见形式,可以对动态规划进行分类,可以参考上一章的内容。

其中线性动态规划的主要特点是状态的推导是按照问题规模 i 从小到大依次推过去的,较大规模的问题的解依赖较小规模的问题的解。

这里问题规模为 i 的含义是考虑前 i 个元素 [0…i] 时问题的解。

线性动态规划简介

线性动态规划的主要特点是状态的推导是按照问题规模 i 从小到大依次推过去的,较大规模的问题的解依赖较小规模的问题的解。

这里问题规模为 i 的含义是考虑前 i 个元素 [0…i] 时问题的解。

状态定义:

dp[n] := [0..n] 上问题的解

状态转移:

dp[n] = f(dp[n-1], ..., dp[0])

从以上状态定义和状态转移可以看出,大规模问题的状态只与较小规模的问题有关,而问题规模完全用一个变量 i 表示,i 的大小表示了问题规模的大小,因此从小到大推 i 直至推到 n,就得到了大规模问题的解,这就是线性动态规划的过程。

按照问题的输入格式,线性动态规划解决的问题主要是单串,双串,矩阵上的问题,因为在单串,双串,矩阵上问题规模可以完全用位置表示,并且位置的大小就是问题规模的大小。因此从前往后推位置就相当于从小到大推问题规模。

线性动态规划是动态规划中最基本的一类。问题的形式、dp 状态和方程的设计、以及与其它算法的结合上面变化很多。按照 dp 方程中各个维度的含义,可以大致总结出几个主流的问题类型,见后面的小节。除此之外还有很多没有总结进来的变种问题,小众问题,和困难问题,这些问题的解法更多地需要结合自己的做题经验去积累,除此之外,常见的,主流的问题和解法都可以总结成下面的四个小类别。

  • 一、单串
  • 二、带维度单串
  • 三、双串
  • 四、矩阵

下面按照这四个小专题刷题

一、单串

单串 dp[i] 线性动态规划最简单的一类问题,输入是一个串,状态一般定义为 dp[i] := 考虑[0..i]上,原问题的解,其中 i 位置的处理,根据不同的问题,主要有两种方式:

  • 第一种是 i 位置必须取,此时状态可以进一步描述为 dp[i] := 考虑[0..i]上,且取 i,原问题的解
  • 第二种是 i 位置可以取可以不取

大部分的问题,对 i 位置的处理是第一种方式,例如力扣:

  • 70 爬楼梯问题
  • 801 使序列递增的最小交换次数
  • 790 多米诺和托米诺平铺
  • 746 使用最小花费爬楼梯

线性动态规划中单串 dp[i] 的问题,状态的推导方向以及推导公式如下

状态推导方向1

1. 依赖比 i 小的 O(1) 个子问题

dp[n] 只与常数个小规模子问题有关,状态的推导过程 dp[i] = f(dp[i - 1], dp[i - 2], ...)。时间复杂度 O(n)O(n),空间复杂度 O(n) 可以优化为 O(1),例如上面提到的 70, 801, 790, 746 都属于这类。

如图所示,虽然紫色部分的 dp[i-1], dp[i-2], ..., dp[0] 均已经计算过,但计算橙色的当前状态时,仅用到 dp[i-1],这属于比 i 小的 O(1) 个子问题。

例如,当 f(dp[i-1], ...) = dp[i-1] + nums[i] 时,当前状态 dp[i] 仅与 dp[i-1] 有关。这个例子是一种数据结构前缀和的状态计算方式,关于前缀和的详细内容请参考下一章。

2. 依赖比 i 小的 O(n) 个子问题

dp[n] 与此前的更小规模的所有子问题 dp[n - 1], dp[n - 2], ..., dp[1] 都可能有关系。

状态推导过程如下:

dp[i] = f(dp[i - 1], dp[i - 2], ..., dp[0])

依然如图所示,计算橙色的当前状态 dp[i] 时,紫色的此前计算过的状态 dp[i-1], ..., dp[0] 均有可能用到,在计算 dp[i] 时需要将它们遍历一遍完成计算。

其中 f 常见的有 max/min,可能还会对 i-1,i-2,...,0 有一些筛选条件,但推导 dp[n] 时依然是 O(n) 级的子问题数量。

例如:

  • 139 单词拆分
  • 818 赛车

以 min 函数为例,这种形式的问题的代码常见写法如下

for i = 1, ..., n
    for j = 1, ..., i-1
        dp[i] = min(dp[i], f(dp[j])

时间复杂度 O ( n 2 ) O(n^{2}) O(n2),空间复杂度 O(n)

单串 dp[i] 经典问题

以下内容将涉及到的知识点对应的典型问题进行讲解,题目和解法具有代表性,可以从一个问题推广到一类问题。

1. 依赖比 i 小的 O(1) 个子问题

  • 53. 最大子数组和

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

一个数组有很多个子数组,求哪个子数组的和最大。可以按照子数组的最后一个元素来分子问题,确定子问题后设计状态

dp[i] := [0..i] 中,以 nums[i] 结尾的最大子数组和

状态的推导是按照 i 从 0 到 n - 1 按顺序推的,推到 dp[i],时,dp[i - 1], ..., dp[0] 已经计算完。因为子数组是连续的,所以子问题 dp[i] 其实只与子问题 dp[i - 1] 有关。如果 [0…i-1] 上以 nums[i-1] 结尾的最大子数组和(缓存在 dp[i-1] )为非负数,则以 nums[i] 结尾的最大子数组和就在 dp[i-1] 的基础上加上 nums[i] 就是 dp[i] 的结果否则以 i 结尾的子数组就不要 i-1 及之前的数,因为选了的话子数组的和只会更小。

按照以上的分析,状态的转移可以写出来,如下

dp[i] = nums[i] + max(dp[i - 1], 0)

这个是单串 dp[i] 的问题,状态的推导方向,以及推导公式如下

状态推导方向1

在本题中,f(dp[i-1], ..., dp[0]) 即为 max(dp[i-1], 0) + nums[i]dp[i] 仅与 dp[i-1] 1 个子问题有关。因此虽然紫色部分的子问题已经计算完,但是推导当前的橙色状态时,只需要 dp[i-1] 这一个历史状态。

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int n = nums.size(); // 数组的长度
        int dp[n]; // dp[i]表示以nums[i]结尾的最大和连续子数组的和
        memset(dp, -1e9, sizeof(dp)); // 数组初始化为最小值
        dp[0] = nums[0]; // 只有一个元素时,最大子数组显然是nums[0]自己
        int res = dp[0];
        for (int i = 1; i < n; i++) {
            if (dp[i - 1] < 0 ) {
                dp[i] = nums[i];
            } else {
                dp[i] = dp[i - 1] + nums[i]; // 因为是连续子数组,所以只和前面一个元素有关
            }
            res = max(dp[i], res); // 更新最大值
        }
        return res;
    }
};

2. 依赖比 i 小的 O(n) 个子问题

  • 300. 最长上升子序列

给定一个无序的整数数组,找到其中最长上升子序列的长度。

输入是一个单串,首先思考单串问题中设计状态 dp[i] 时拆分子问题的方式:枚举子串或子序列的结尾元素来拆分子问题,设计状态 dp[i] := 在子数组 [0..i] 上,且选了 nums[i] 时,的最长上升子序列。

因为子序列需要上升,因此以 i 结尾的子序列中,nums[i] 之前的数字一定要比 nums[i] 小才行,因此目标就是先找到以此前比 nums[i] 小的各个元素,然后每个所选元素对应一个以它们结尾的最长子序列,从这些子序列中选择最长的,其长度加 1 就是当前的问题的结果。如果此前没有比 nums[i] 小的数字,则当前问题的结果就是 1 。

按照以上的分析,状态的转移方程可以写出来,如下

d p [ i ] = m a x j ( d p [ j ] ) + 1 dp[i] = max_{j}(dp[j]) + 1 dp[i]=maxj(dp[j])+1

其中 0 ≤ j < i , n u m s [ j ] < n u m s [ i ] 0 \leq j < i, nums[j] < nums[i] 0j<i,nums[j]<nums[i]

本题依然是单串 dp[i] 的问题,状态的推导方向,以及推导公式与上一题的图示相同,

状态的推导依然是按照 i 从 0 到 n-1 推的,计算 dp[i] 时,dp[i-1], dp[i-2], ..., dp[0] 依然已经计算完。

但本题与上一题的区别是推导 dp[i] 时,dp[i-1]. dp[i-2], ..., dp[0] 均可能需要用上,即,因此计算当前的橙色状态时,紫色部分此前计算过的状态都可能需要用上。

单串相关练习题

    1. 最经典单串 LIS 系列
    1. 最大子数组和系列
    1. 打家劫舍系列
    1. 变形:需要两个位置的情况
    1. 与其它算法配合
    1. 其它单串 dp[i] 问题
    1. 带维度单串 dp[i][k]
    1. 股票系列

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

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

相关文章

【IM苹果推iMessage】苹果真机推送自动分配任务,自动分配任务,让您瞄准中高端客户

推荐内容IMESSGAE相关 作者✈️IMEAE推荐内容iMessage苹果推软件 *** 点击即可查看作者要求内容信息作者✈️IMEAE推荐内容1.家庭推内容 *** 点击即可查看作者要求内容信息作者✈️IMEAE推荐内容2.相册推 *** 点击即可查看作者要求内容信息作者✈️IMEAE推荐内容3.日历推 *** …

代码命名规范的套路是真优雅呀,命名如歌,代码如诗

日常编码中&#xff0c;代码的命名是个大的学问。能快速的看懂开源软件的代码结构和意图&#xff0c;也是一项必备的能力。那它们有什么规律呢&#xff1f; Java项目的代码结构&#xff0c;能够体现它的设计理念。Java采用长命名的方式来规范类的命名&#xff0c;能够自己表达…

ansible常用命令

目录 1、列出默认清单文件中的所有受管主机 2. 列出自定义清单文件中的所有受管主机&#xff08;自定义清单文件&#xff1a;inventory&#xff09; 3、运行playbook 4、创建需要输入文件密码的加密的文件 5、创建用密码文件的加密的文件 6、查看加密的文件内容 7、向已有…

学会使用Git,看这一篇文章就够了

文章目录 一、背景二、Git的安装2.1 Windows下安装Git&#xff1a;下载安装包安装Git配置Git 2.2 Linux下安装Git&#xff1a;更新系统安装Git配置Git 三、Git 基本使用3.1 初始化 Git 仓库3.2添加文件3.3 提交代码3.4 查看历史记录3.5创建分支3.6 修改文件3.7 查看文件状态3.8…

【实用工具】JSR-269 插入式注解处理器AbstractProcessor

JSR-269原理浅析 初次使用lombok时&#xff0c;都需要在idea安装lombok插件&#xff0c;这让我们怀疑lombok的实现是通过提供自己的编译器实现的&#xff0c;然而实际情况并非如此&#xff0c;在脱离idea使用javac编译时&#xff0c;只要类路径有lombok的jar包&#xff0c;项目…

Android-源码分析-分析手机热点里的AP Band(频段)被隐藏/置灰的原因?

本博文记录寻找手机热点中AP Band(频段)被隐藏/置灰的原因&#xff0c;相似问题同理去查找解决。 先放上一张MTK平台手机-热点-AP Band界面效果图&#xff1a; 很明显&#xff0c;界面中的AP Band选项变灰&#xff0c;无法点击编辑修改内容&#xff0c;如果是AP Band 被隐藏或…

C#,生信软件实践(01)——DNA序列数据库FASTA文件合并工具的源代码

1 生物信息学简介 生物信息学&#xff08;BioInformatics&#xff09;是研究生物信息的采集、处理、存储、传播&#xff0c;分析和解释等各方面的学科&#xff0c;也是随着生命科学和计算机科学的迅猛发展&#xff0c;生命科学和计算机科学相结合形成的一门新学科。它通过综合…

JavaWeb ( 四 ) JavaEE

2.JavaEE 2.1.Java版本 J2SE : 适用于桌面系统的Java 2平台标准版&#xff08;Java 2 Platform Standard Edition&#xff0c;J2SE&#xff09; J2EE : 适用于创建服务器应用程序和服务的Java 2平台企业版&#xff08;Java 2 Platform Enterprise Edition&#xff0c;J2EE&a…

学企业管理

工业社会的代表产品是交通运输设备&#xff0c;如火车/高铁、汽车、飞机/火箭、船舶/航母&#xff0c;其核心是发动机。信息社会的代表产品是计算设备&#xff0c;如大型机小型机、工作站/PC台式机电脑/PC笔记本电脑/PC平板电脑、智能手机。 汽车这个产品&#xff0c;既属于高精…

调试别人的API,一般有哪些步骤?

当我们使用了一些由别人实现的API接口时&#xff0c;该如何进行调试呢&#xff1f;当我们使用的API返回一些意想不到错误时&#xff0c;该怎么办呢?这个问题可能是由于用户输入或者API本身&#xff0c;或者其他完全无关的内容等引起的。调试是我们进行定位并修复由单个API调用…

漫天花雨HTML特效+3D相册

大家好&#xff0c;我是csdn的博主&#xff1a;lqj_本人 这是我的个人博客主页&#xff1a; lqj_本人的博客_CSDN博客-微信小程序,前端,python领域博主lqj_本人擅长微信小程序,前端,python,等方面的知识https://blog.csdn.net/lbcyllqj?spm1011.2415.3001.5343哔哩哔哩欢迎关注…

软件工程期末复习(背题家速成)

文章目录 前言一、选择题1、第一章 软件工程综述2、第二章 软件过程3、第三章 可行性研究4、第四章 结构化需求分析5、第五章 结构化软件设计6、第六章 面向对象的需求分析7、第七章 第7章面向对象设计8、第八章 基于构件的开发9、第九章 软件项目的测试10、第十章 软件实施、维…

每天一道算法练习题--Day2 第一章 --算法专题 --- ----------位运算

我这里总结了几道位运算的题目分享给大家&#xff0c;分别是 136 和 137&#xff0c; 260 和 645&#xff0c; 总共加起来四道题。 四道题全部都是位运算的套路&#xff0c;如果你想练习位运算的话&#xff0c;不要错过哦&#xff5e;&#xff5e; 前菜 开始之前我们先了解下…

Umi 插件实战教程

引言 笔者最近开发了一款 umi 插件&#xff1a;plugin-umi-cmdk[1],该插件的功能主要是&#xff1a;在 umi 项目里可以方便的集成 cmd k &#xff0c;实现菜单等搜索。 主体功能并不复杂&#xff0c;但是在集成作为 umi 插件过程中踩了不少坑&#xff0c;主要是 umi 官方文档的…

【计算机网络】面试高频问题汇总及详细解答

【C语言部分】面试高频问题汇总及详细解答 【操作系统(Linux)】面试高频问题汇总及详细解答 【数据库】面试高频问题汇总及详细解答 本文目录 1. 简述网络七层参考模型及每一层的作用2. 简述静态路由和动态路由3. 说说有哪些路由协议&#xff0c;都是如何更新的4. 简述域名解析…

PostgreSQL Explain 复杂执行计划怎么看 --- 逐个分解PG执行计划的那些操作

开头还是介绍一下群&#xff0c;如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;在新加的朋友会分到2群&#xff08;共…

Codeforces-Round-805-Div-3-E-Split-Into-Two-Sets

title: Codeforces Round 805 (Div. 3) E. Split Into Two Sets date: 2023-04-25 18:14:41 categories: AlgorithmCodeforces tags:codeforces并查集1600 E. Split Into Two Sets 题目大意 给你n组数&#xff0c;每组里面有两个数字&#xff0c;问你能不能把这n组数分为两组…

【数据架构系列-06】一文搞懂数据模型的3种类型——概念模型、逻辑模型、物理模型

数据模型就是模拟现实世界的方法论&#xff0c;是通向智慧世界的基石&#xff01; 从现实世界发展到智慧世界&#xff0c;要数经历现实世界、信息世界、计算机世界、数据世界、智慧世界五个不同的世界&#xff0c;我们天生具有从混沌的世界抽象信息变为信息世界的能力&#xff…

基于jenkinsfile布置java工程

需求 通过jenkins发布java项目到服务器 预备环境 项目地址&#xff1a; https://gitee.com/asaland/sb-docker-appJenkins 2.387.3 通过Jenkinsfile实现方式 jenkins ui 配置pipeline 什么是pipeline? 直接看注释吧&#xff0c;简单点就是编排可以多个跨时间的构建代理…

JavaScript全解析——canvas 绘制变换和渐变

绘制变换 ●在 cancas 内, 也可以向 css 中一样, 出现一些 2d 变换的效果 ●先来绘制一个基本矩形 // 0. 获取到页面上的 canvas 标签元素节点 const canvasEle document.querySelector(#canvas)// 1. 获取当前这个画布的工具箱 const ctx canvasEle.getContext(2d)// 2. 绘…