详详详解动归数组常见习题(C/C++)

文章目录

    • 最长递增数组序列(必须连续)dp[i] = dp[i - 1] + 1;
    • 最长递归子序列(不需要连续)dp[i] = max(dp[i], dp[j] + 1);俩层循环
    • 总结一维dp
    • 最长重复子数组
    • 最长公共子序列
    • 总结二维dp
    • 最终目标[3692. 最长连续公共子序列 - AcWing题库](https://www.acwing.com/problem/content/3695/)

最长递增数组序列(必须连续)dp[i] = dp[i - 1] + 1;

image-20240410165824281

这个的动态规划比下一个简单一些,但其实大差不差,这个的j不需要遍历i以前的元素,因为我们不求子序列,但是下面的就得求i以前区间的,本题如果不满足 nums[i] > nums[j] 的话 ,那么直接 j=i;更新j指针位置,重新开始计算就好了

卡尔哥完整代码:

image-20240410181226265

其实根本不需要定义 j 变量,直接 i 与 i-1比较就好了~~

最长递归子序列(不需要连续)dp[i] = max(dp[i], dp[j] + 1);俩层循环

用动态规划

10,9,2,5,3,7,101,18

这组数据放在上个题目的答案就是:3 7 101 三个结果

放在这个题目就是:2 5 7 101 四个结果 这就是子序列的区别

dp[i] 表示:最长子序列的长度(以nums[i]结尾的最长递增子序列的长度

image-20240410170858904

我们的 j 是从 i 以前的区间开始寻找,并不是说i前一个+1就是得到的最终值

每一次j在i之前寻找元素的时候,都会出现一个新的 dp[i] ,所以我们最终的 dp[i] 也要从众多 dp[i] 中找出最大的

image-20240410171345552

int lengthOfLIS(int* nums, int numsSize) {int dp[numsSize];for (int i = 0; i < numsSize; i++) {dp[i] = 1; // 初始状态,每个数字自身构成长度为 1 的子序列for (int j = 0; j < i; j++) {if (nums[j] < nums[i]) {dp[i] = fmax(dp[i], dp[j] + 1); // 更新 dp[i]}}}int ans = 0;for (int i = 0; i < numsSize; i++) {ans = fmax(ans, dp[i]); // 寻找 dp 数组中最大的值}return ans;
}

总结一维dp

子序列:i 前面的每一个区间的元素 j都要去遍历

必须连续:dp[i] 只与 i 前一个位置 j 进行判断加法

image-20240410180358826

image-20240410181226265

我的代码写的还是太笨了,完全没必要定义 j 变量嘟!!!

最长重复子数组

动态规划之子序列问题,想清楚DP数组的定义 | LeetCode:718.最长重复子数组_哔哩哔哩_bilibili

暴力的话,至少是O(N^3) 复杂度非常高

dp数组的含义: dp [i] [j] i 表示 到了nums1数组的元素下标 j 表示到了nums2数组的元素下标

表示 以i-1为结尾的 nums1 和 j-1为结尾的nums2的最长重复子数组长度 也就是说 我们的 dp[i] [j] 的下标比数组慢一步

(以i结尾,以j结尾这样定义后续会很不方便)

递推公式:if(nums1[i-1]==nums2[j-1])dp [i] [j] =dp[i-1] [j-1] +1; 因为我们是以 i-1 j-1 为结尾的dp数组

初始化:根据我们的定义表示,dp[i] [0] dp[0] [j] 都是没有意义的,所以必须初始化为0;对于其他数字我们也可以初始化为0,因为后续也会覆盖,所以直接全部初始化成0就好了

本题也可以进行状态压缩,为了防止覆盖也是从后往前(担心一个值放俩次),类似于01背包

拓展:为什么 i-1 j-1 为结尾 这样初始化很方便,而且越界问题也随着初始化被解决掉了

A: 1 2 3 2 1

B 0 0 0 0 0 0

3 0 0 0 1 0 0

2 0 0 1 0 2 0

1 0 1 0 0 0 3

4 0 0 0 0 0 0

7 0 0 0 0 0 0

image-20240411103530733

如果dp数组定义为 i结尾 j结尾的 ,那么就是下面这样:我们必须对刚开始第一行也得初始化判断,而且还要担心越界问题

0 1 2 3 2 1

3 0 0 1 0 0

2 0 1 0 2 0

1 1 0 0 0 3

4 0 0 0 0 0

7 0 0 0 0 0

#include<bits/stdc++.h>
using namespace std;
class Solution {
public:int findLength(vector<int>& nums1, vector<int>& nums2) {vector<vector<int>> dp (nums1.size() + 1, vector<int>(nums2.size() + 1, 0));int result=0;//代码循环细节,正常来说我们的size就是元素个数,不是数组边界的大小,那么我们i初始化成1 循环终止条件为 i<=size 这样是会发生越界的 但是由于我们的dp数组定义的是 i-1 j-1 为下标的数组,所以我们必须要到达边界,这样才可以访问到我们的最后一个元素 无论是最长递增 还是最长公共 都是 i<nums1Size 这样子的 说明细节真的很多for(int i=1;i<=nums1.size();i++){for(int j=1;j<=nums2.size();j++){if(nums1[i-1]==nums2[j-1])//这个if条件就忘了写了 光顾着写递推公式 连最基本的条件判断都没写{dp[i][j]=dp[i-1][j-1]+1;}if(dp[i][j] > result) result =dp[i][j];//不需要再遍历一次二维数组,我们通过result顺便保存}}for(size_t i=0;i<=nums1.size();i++){for(size_t j=0;j<=nums2.size();j++){cout << dp[i][j] << " ";}cout << endl;}return result;}
};
int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);Solution s;vector<int>nums1={1,2,3,2,1};vector<int>nums2={3,2,1,4,7};s.findLength(nums2,nums1);return 0;
}

代码中有一个很大的bug:int dp [nums1Size+1] [nums2Size+1]={{0}}; //报错原因 不支持动态开辟二维数组

所以我们还是用vector来进行初始化和运算更方便一些

vector<vector> dp (nums1.size() + 1, vector(nums2.size() + 1, 0));

代码解释:这里运用了构造,nums.size()+1个vector,每一个vector又是nums2.size()+1个0

最长公共子序列

0 a b c d e

0 0 0 0 0 0 dp[0] [j]

a 0 1 1 1 1 1

c 0 1 1 2 2 2

e 0 1 1 2 2 3

image-20240411154221999

dp[i] [j]:表示以 i-1 j-1 的最长公共子序列 一般来说 dp中用来二维的都是定义到 i-1 j-1 其实也很好理解 就像蓝桥杯的扫雷那个题目,我们如果对数组不进行扩充处理的话,就要对第一行和第一列进行特殊情况的判断,这个道理在本题中也是同样的道理

递推公式: if(nums1[i-1]==nums2[j-1])dp [i] [j] =dp[i-1] [j-1] +1;

为什么我们if条件中写的是 i-1 j-1 呢?因为我们是以 i-1 j-1 为结尾的dp数组

if(nums1[i-1] != nums2[j-1])

对于 a b c 与 a c e 此时c 与 e不相同 那么 我们可能考虑 a b c与 a c匹配 :dp[i] [j-1]

对于 a b c 与 a c e 我们也可能考虑 a c e与 a b匹配 :dp[i-1] [j]

这俩种情况都有可能是我们的dp[i] [j]

image-20240411152427568

初始化:我们的第一行第一列全部初始化为0 含义是 空字符与字符匹配结果为0

而且我们遍历的时候是 从左往右 从上往下遍历

而且这个题目不需要去遍历寻找最大值 dp[text1.size()] [text2.size()] 就是我们最终求得的结果 与上题的result不一样

总结二维dp

1.初始化

vector<vector<int> > dp (text1.size()+1,vector<int>(text2.size()+1,0));

刚开始多初始化一行一列,对于解决二维dp有大帮助,省去越界与单独情况特判的麻烦

2.递推公式

if(nums1[i-1]==nums2[j-1])dp [i] [j] =dp[i-1] [j-1] +1;

这其实就是斜对角线

3.代码对比

image-20240411154715253

不同点:

返回值的返回方式不同

递推公式不同,子序列要考虑更多的情况

相同点:

初始化的方式相同

循环控制的终止条件相同

最终目标3692. 最长连续公共子序列 - AcWing题库

最长连续公共子序列 = 最长重复子数组的题目 递推公式只有一个,求的不是子序列而是连续的

将上述代码改吧改吧

#include<bits/stdc++.h>
using namespace std;
class Solution {
public:int findLength(string& nums1, string& nums2) {vector<vector<int>> dp (nums1.size() + 1, vector<int>(nums2.size() + 1, 0));int result=0;for(int i=1;i<=nums1.size();i++){for(int j=1;j<=nums2.size();j++){if(nums1[i-1]==nums2[j-1])//这个if条件就忘了写了 光顾着写递推公式 连最基本的条件判断都没写{dp[i][j]=dp[i-1][j-1]+1;}if(dp[i][j] > result) result =dp[i][j];//不需要再遍历一次二维数组,我们通过result顺便保存}}return result;}
};
int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);Solution s;string s1;string s2;cin >> s1;cin >> s2;cout << s.findLength(s1,s2);return 0;
}

image-20240411184825879

关于有序字符的输出,现在的我还是无法解决…

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

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

相关文章

【C++庖丁解牛】C++11---lambda表达式 | 包装器

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 1. lambda表达式1.1 C98中…

ip地址与硬件地址的区别是什么

在数字世界的浩瀚海洋中&#xff0c;每一台联网的设备都需要一个独特的标识来确保信息的准确传输。这些标识&#xff0c;我们通常称之为IP地址和硬件地址。虽然它们都是用来识别网络设备的&#xff0c;但各自扮演的角色和所处的层次却大相径庭。虎观代理小二将带您深入了解IP地…

主成分分析在R语言中的简单应用:使用mvstats包

在数据科学领域&#xff0c;主成分分析&#xff08;PCA&#xff09;是一种广泛使用的技术&#xff0c;主要用于数据降维和探索性数据分析。PCA可以帮助我们发现数据中的模式&#xff0c;减少数据集的复杂性&#xff0c;同时保持数据中最重要的特征。本文将介绍如何在R语言中使用…

PID详解汇总

一、参照文章 PID的各种算法优缺点 二、位置式PID 优点:静态误差小,溢出的影响小。 缺点:计算量很大&#x

【PCL】教程 example2 3D点云之间的精确配准(FPFH特征对应关系估计变换矩阵)

这段代码主要实现了点云之间的配准功能&#xff0c;旨在通过估计点云的特征并找到最佳的对应关系来计算一个变换矩阵&#xff0c;从而可以将源点云&#xff08;src&#xff09;变换到目标点云&#xff08;tgt&#xff09;的坐标系统中。 代码功能和方法总结如下&#xff1a; 估…

上位机开发PyQt5(二)【单行输入框、多行输入框、按钮的信号和槽】

目录 一、单行输入框QLineEdit QLineEdit的方法&#xff1a; 二、多行输入框QTextEdit QTextEdit的方法 三、按钮QPushButton 四、按钮的信号与槽 信号与槽简介&#xff1a; 信号和槽绑定&#xff1a; 使用PyQt的槽函数 一、单行输入框QLineEdit QLineEdit控件可以输入…

黑马点评项目个人笔记+项目优化调整

博客须知 本篇博客内容来源与黑马点评项目实战篇-16.用户签到-实现签到功能_哔哩哔哩_bilibili&#xff0c;作者对视频内容进行了整合&#xff0c;由于记笔记时图片使用的是本地路径&#xff0c;所以导致博客的图片无法正常显示&#xff0c;如果有图片需求可以下载上方的pdf须…

程序员老鸟的 Pascal 语言菜鸟教程 -- 快速体验 Pascal

有些程序设计语言和编译器教材会以pascal语言的程序为例&#xff0c;这里写一个快速掌握简单应用的介绍。 1&#xff0c;安装 free pascal 编译器 ubuntu 22.04 直接通过 apt 源安装&#xff0c;此时的版本号为 3.2.2 1.1 安装 sudo apt install fp-compiler 1.2 简单测试 fpc…

【maven】pom文件详解和延伸知识

【maven】pom文件详解 【一】maven项目的pom文件详解【1】maven项目的目录结构【2】根元素和必要配置【3】父项目和parent元素【4】项目构建需要的信息【5】项目依赖相关信息&#xff08;1&#xff09;依赖坐标&#xff08;2&#xff09;依赖类型&#xff08;3&#xff09;依赖…

JavaScript this 上下文深度探索:综合指南涵盖隐式与显式call、apply、bind、箭头函数、构造函数等用法于多样场景

JavaScript中的this关键字代表函数执行的上下文环境&#xff0c;核心在于确定函数内部访问的当前对象。它根据函数调用方式动态变化&#xff0c;对事件处理、对象方法调用等至关重要。通过.call(), .apply(), .bind()或箭头函数控制this&#xff0c;可确保代码逻辑正确绑定对象…

python可视化学习笔记折线图问题-起始点问题

问题描述&#xff1a; 起始点的位置不对 from pyecharts.charts import Line import pyecharts.options as opts # 示例数据 x_data [1,2,3,4,5] y_data [1, 2, 3, 4, 5] # 创建 Line 图表 line Line() line.add_xaxis(x_data) line.add_yaxis("test", y_data) li…

Redis---------缓存更新,缓存穿透\雪崩\击穿

三种更新策略 内存淘汰是Redis内存的自动操作&#xff0c;当内存快满了就会触发内存淘汰。超时剔除则是在存储Redis时加上其有限期(expire)&#xff0c;有限期一过就会自动删除掉。而主动更新则是自己编写代码去保持更新&#xff0c;所以接下来研究主动更新策略。 主动更新策略…

PS入门|网络报名证件照上传总提示审核失败是什么原因?

前言 之前小白遇到过有小伙伴报考了某个证书的考试&#xff0c;但在报名的过程出现了问题&#xff1a;证件照都是按照要求制作的&#xff0c;但为啥总是没有审核通过&#xff1f; 这个很简单&#xff1a;分辨率出现了问题。 啥&#xff1f;明明都是按照软件提示的分辨率要求制…

Python中的观察者模式及其应用

观察者模式是设计模式之一&#xff0c;实现一对多依赖&#xff0c;当主题状态变化时通知所有观察者更新。在Python中&#xff0c;通过自定义接口或内置模块实现观察者模式&#xff0c;可提高程序灵活性和扩展性&#xff0c;尤其适用于状态变化时触发操作的场景&#xff0c;如事…

Linux(ubuntu)—— 用户管理user 用户组group

一、用户 1.1、查看所有用户 cat /etc/passwd 1.2、新增用户 useradd 命令&#xff0c;我这里用的是2.4的命令。 然后&#xff0c;需要设置密码 passwd student 只有root用户才能用passwd命令设置其他用户的密码&#xff0c;普通用户只能够设置自己的密码 二、组 2.1查看…

【右一的开发日记】全导航,持续更新...

文章目录 &#x1f4da;前端【跟课笔记】&#x1f407;核心技术&#x1f407;高级技术 &#x1f4da;捣鼓捣鼓&#x1f407;小小案例&#x1f407;喵喵大王立大功&#x1f407;TED自用学习辅助网站&#x1f407;世界top2000计算机科学家可视化大屏&#x1f407;基于CBDB的唐代历…

中间件之异步通讯组件RabbitMQ入门

一、概述 微服务一旦拆分&#xff0c;必然涉及到服务之间的相互调用&#xff0c;目前我们服务之间调用采用的都是基于OpenFeign的调用。这种调用中&#xff0c;调用者发起请求后需要等待服务提供者执行业务返回结果后&#xff0c;才能继续执行后面的业务。也就是说调用者在调用…

HTTP/1.1、HTTP/2、HTTP/3 的演变

HTTP/1.1、HTTP/2、HTTP/3 的演变 HTTP/1.1 相比 HTTP/1.0 提高了什么性能&#xff1f;HTTP/2 做了什么优化&#xff1f;HTTP/3 做了哪些优化&#xff1f; HTTP/1.1 相比 HTTP/1.0 提高了什么性能&#xff1f; HTTP/1.1 相比 HTTP/1.0 性能上的改进&#xff1a; 使用长连接的…

分拣机器人也这么卷了吗?!

导语 大家好&#xff0c;我是智能仓储物流技术研习社的社长&#xff0c;老K。专注分享智能仓储物流技术、智能制造等内容。 新书《智能物流系统构成与技术实践》 智能制造-话题精读 1、西门子、ABB、汇川&#xff1a;2024中国工业数字化自动化50强 2、完整拆解&#xff1a;智能…

4月20日,杭州Sui Meetup活动回顾

4 月 20 日在风景如画的杭州&#xff0c;「TinTin DESTINATION MOON」成功举办。此次活动深入探讨了 Sui 生态系统的演进及未来机遇&#xff0c;包括 Sui 上的资产管理协议 Mole、全链引擎 Obelisk Engine 以及 Generator 的开发范式等热点话题&#xff0c;行业专家提供了深刻见…