C国演义 [第七章]

news2025/1/11 20:07:37

第七章

  • 最长重复子数组
    • 题目理解
    • 步骤
      • dp含义
      • 递推公式
      • 初始化
        • 为啥dp数组如此奇怪
      • 遍历顺序
    • 代码
  • 最长公共子序列
    • 题目理解
    • 步骤
      • dp含义
      • 递推公式
      • 初始化
      • 遍历顺序
    • 代码
  • 总结

最长重复子数组

力扣链接

给两个整数数组 nums1 和 nums2 ,返回 两个数组中 公共的 、长度最长的子数组的长度 。

示例 1:
输入:nums1 = [1,2,3,2,1], nums2 = [3,2,1,4,7]
输出:3
解释:长度最长的公共子数组是 [3,2,1] 。
示例 2:
输入:nums1 = [0,0,0,0,0], nums2 = [0,0,0,0,0]
输出:5

  • 提示:
    1 <= nums1.length, nums2.length <= 1000
    0 <= nums1[i], nums2[i] <= 100

题目理解

暴力解法就是 用两个for循环遍历两个数组, 然后在套用一个while循环或者for循环从各个起始位置开始判断
这样就相当于套用了三个for循环, 数据大了就会超时

其实本题采用的方法是动态规划, 用个二维dp数组来记录比较情况

步骤

dp含义

重复子数组, 里面有个暗含意思 连续
dp[i][j] — — 以下标 i - 1为结尾的nums1, 以下标 j - 1 结尾的nums2 之间的最长重复子数组的长度

🗨️为啥是以 下标 i - 1结尾 而不是以下标 i 结尾呢??

  • 其实这也是为了方便初始化 和 后续的判断
    后面在 为啥dp数组如此奇怪 中有讲

递推公式

重复子数组, 里面有个暗含意思 连续
那么, 我们处理的方法 就和前面的 连续递增子序列 相同

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

🗨️为啥比较的是 nums1[i - 1] 和 nums[j - 1], 而不是 nums1[i] 和 nums[j]呢

  • dp数组的含义是 以下标 i - 1为结尾的nums1, 以下标 j - 1 结尾的nums 之间的最长重复子数组的长度
    因为题目有 连续 的意思, 所以 dp[i][j] 的来源只有一个, 那就是 dp[i - 1][j - 1]
    条件就是判断 当前两数组的值是否相等 — — nums1[i - 1] == nums2[ j - 1]
    如果判断相等, 那么 dp[i][j] 就会在dp[i - 1][j - 1]的基础上 + 1 (两者都回退一步, 同时看看后面的值是否相等)

初始化


第一行 和 第一列要初始化一下.
那么我们需要初始化的是 dp[0][j] 和 dp[i][0]
但是, 我们定义的dp数组的含义 — — 以下标 i - 1为结尾的nums1, 以下标 j - 1 结尾的nums2 之间的最长重复子数组的长度
那么, 就是要初始化一下 -1行 和 -1列, 可想而知: 要初始化为 0
其它的要怎么初始化呢? — — 由前面到后面进行推导, 由上面到下面进行推导 — — 反正都是由前面的推导而来, 那么我们就初始化为 0

那么我们就全部都初始化为 0

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

为啥dp数组如此奇怪

如果我们的dp数组的含义是 — — 以下标 i为结尾的nums1, 以下标 j为结尾的nums2之间的最长重复子数组的长度
那么, 初始化就要初始化 第1行 和 第 1列
如果nums1[i] 与 nums2[0] 相同的话,对应的 dp[i][0]就要初始为1, 因为此时最长重复子数组为1。 nums2[j] 与 nums1[0]相同的话,同理。

// 要对第一行,第一列经行初始化
for (int i = 0; i < nums1.size(); i++) if (nums1[i] == nums2[0]) dp[i][0] = 1;
for (int j = 0; j < nums2.size(); j++) if (nums1[0] == nums2[j]) dp[0][j] = 1;

遍历顺序


是从左上方开始递推的 — — 从前到后, 从上至下开始遍历

代码

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;
        for(int i = 1; i <= nums1.size(); i++)
        {
            for(int j = 1; j <= nums2.size(); j++)
            {
                if(nums1[i - 1] == nums2[j - 1])
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                
                result = max(result, dp[i][j]);
            }

        }
        
        return result;

    }
};

在这里, 我们也给出 dp数组的含义是 — — 下标以 i - 1为结尾的nums1, 下标以 j - 1为结尾的nums2之间的最长重复子序列的长度👇👇👇

class Solution {
public:
    int findLength(vector<int>& nums1, vector<int>& nums2) 
    {
        vector<vector<int>> dp(nums1.size(), vector<int>(nums2.size(), 0));
        
        // 要对第一行,第一列经行初始化
        for (int i = 0; i < nums1.size(); i++) if (nums1[i] == nums2[0]) dp[i][0] = 1;
        for (int j = 0; j < nums2.size(); j++) if (nums1[0] == nums2[j]) dp[0][j] = 1;
        
        int result = 0;
        for(int i = 0; i < nums1.size(); i++)
        {
            for(int j = 0; j < nums2.size(); j++)
            {
                if(i > 0 && j > 0 && nums1[i] == nums2[j]) // 为了预防i - 1 和 j - 1是负数
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                
                result = max(result, dp[i][j]);
            }

        }
        
        return result;

    }
};

最长公共子序列

力扣链接

给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 .

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串.

例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列.
两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列.

示例 1:
输入:text1 = “abcde”, text2 = “ace”
输出:3
解释:最长公共子序列是 “ace” ,它的长度为 3 。
示例 2:
输入:text1 = “abc”, text2 = “abc”
输出:3
解释:最长公共子序列是 “abc” ,它的长度为 3 。
示例 3:
输入:text1 = “abc”, text2 = “def”
输出:0
解释:两个字符串没有公共子序列,返回 0 。

  • 提示:
    1 <= text1.length, text2.length <= 1000
    text1 和 text2 仅由小写英文字符组成

题目理解

这个题目是 不讲究连续 && 公共子序列
由此可以联想到 最长递增子序列
区别就是 : 一个是一个集合, 另一个是两个集合 — — 一个是一维dp数组, 另一个是二维dp数组

步骤

dp含义

dp[i][j] — — 区间为[0, i - 1]的nums1 和 区间为[0, j - 1]的nums2之间的最长公共子序列的长度
这里为啥是区间 i - 1 和 j - 1, 这个在上面已经说过了.

递推公式

无非就两种情况: nums1[i - 1] 和 nums2[j - 1] 是否相等

  • 如果nums1[i - 1] == nums2[j - 1] — — 那么就使用dp[i - 1][j - 1]的情况 — — dp[i - 1][j - 1] + 1
  • 如果nums1[i - 1] != nums2[j - 1] — — 那么就比较 区间为[0, i - 1]的nums1 和 区间为[0, j - 2]的nums2之间的最长公共子序列的长度(dp[i][j - 1]) 和 区间为[0, i - 2]的nums1 和 区间为[0, j - 1]的nums2之间的最长公共子序列的长度(dp[i - 1][j])
	if(nums1[i - 1] == nums2[j - 1])
		dp[i][j] = dp[i - 1][j - 1] + 1;
	else
		dp[i][j] = max(dp[i][j - 1], dp[i -1][j]);

初始化


通过递推公式可知, 我们要初始化第一行 和 第一列
即我们需要初始化的是 dp[0][j] 和 dp[i][0]
但是, 我们dp数组的含义是 — — 区间为[0, i - 1]的nums1 和 区间为[0, j - 1]的nums2之间的最长公共子序列的长度
那么, dp[0][j] 的含义就是 -1 行 — — 那就初始化为 0 , dp[i][0]亦是如此
那么, 其他的dp数组呢? — — 由前面递推过来的, 所以就初始化为 0也是可以的

所以, 我们就把 dp数组都初始化为 0

遍历顺序


通过递推公式可知, 是 从前到后, 从上至下的顺序 --- --- 从小到大的遍历顺序

代码

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) 
    {
        vector<vector<int>> dp(text1.size() + 1, vector<int>(text2.size() + 1, 0));
        
        for(int i = 1; i <= text1.size(); i++)
        {
            for(int j = 1; j <= text2.size(); j++)
            {
                if(text1[i - 1] == text2[j - 1])
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                else
                    dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]);
            }

        }
        
        return dp[text1.size()][text2.size()];
    }
};

总结

通过前面几章的动态规划刷题篇的训练, 我们不难发现

  • dp数组的含义是非常重要的, 这也决定了后面的递推公式的得出
  • 递推公式涉及 i - 1 或者是 j - 1的, 建议从 1开始遍历好一些, 这样也避免了一些情况的讨论

贵有恒,何必三更起五更眠;最无益,只怕一日曝十日寒 — — 毛泽东

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

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

相关文章

设计模式之中介者模式笔记

设计模式之中介者模式笔记 说明Mediator(中介者)目录中介者模式示例类图抽象中介者类抽象同事类租房者类房主类具体的中介者角色类测试类 说明 记录下学习设计模式-中介者模式的写法。JDK使用版本为1.8版本。 Mediator(中介者) 意图:用一个中介对象来封装一系列的对象交互。…

剑指 Offer 68 - II. 二叉树的最近公共祖先 / LeetCode 236. 二叉树的最近公共祖先(搜索与回溯)

题目&#xff1a; 链接&#xff1a;剑指 Offer 68 - II. 二叉树的最近公共祖先&#xff1b;LeetCode 236. 二叉树的最近公共祖先 难度&#xff1a;中等 上一题博客&#xff1a;剑指 Offer 68 - I. 二叉搜索树的最近公共祖先 / LeetCode 235. 二叉搜索树的最近公共祖先&#xf…

python:并发编程(二十四)

前言 本文将和大家一起探讨python并发编程的实际项目&#xff1a;win图形界面应用&#xff08;篇六&#xff0c;共八篇&#xff09;&#xff0c;系列文章将会从零开始构建项目&#xff0c;并逐渐完善项目&#xff0c;最终将项目打造成适用于高并发场景的应用。 本文为python并…

Pandas进阶修炼120题-第二期(Pandas数据处理,21-50题)

文章目录 Pandas进阶修炼120题第二期 Pandas数据处理21.读取本地EXCEL数据22.查看df数据前5行23.将salary列数据转换为最大值与最小值的平均值方法一&#xff1a;正则表达式&#xff08;分别使用apply()&#xff0c;applymap(),map()来实现&#xff09;方法二&#xff1a;apply…

wifi芯片原理

一、在系统中的位置 基带&#xff08;baseband&#xff09; 基带的作用有三个&#xff1a; 1、队列包的管理 2、调试解调 3、CSMA/CA机制 CSMA/CA的全称是Carrier Sense Multiple Access with Collision Avoidance&#xff0c;即载波侦听多路访问&#xff0f;冲突避免。 各…

java——集合框架

文章目录 接口实现&#xff08;类&#xff09;算法1. 排序算法2. 查找算法3. 拷贝算法4. 填充算法5. 比较算法6. 随机算法7. 迭代器算法8. 交集、并集、差集9. 分割集合10. 数组和集合的互转 集合框架是一个用来代表和操纵集合的统一架构。所有的集合框架都包含如下内容&#x…

C++手撕红黑树

目录&#xff1a; 红黑树的概念红黑树的性质红黑树节点的定义 红黑树结构红黑树的插入操作红黑树的验证红黑树的代码实现 红黑树的删除红黑树与AVL树的比较红黑树的应用 总结 红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结…

DevOps系列文章之 Spring Boot Docker打包

应用准备容器化&#xff0c;因为几十个应用从测试到发布太麻烦了&#xff0c;而且还会因为环境的因素导致部署中出现各种问题。为了在开发、测试、生产都能保持一致的环境&#xff0c;就引进了容器技术&#xff0c;而目前常用的应用使用基于spring boot的。 在Spring Boot应用…

AI数字人之语音驱动面部模型及超分辨率重建Wav2Lip-HD

1 Wav2Lip-HD项目介绍 数字人打造中语音驱动人脸和超分辨率重建两种必备的模型&#xff0c;它们被用于实现数字人的语音和图像方面的功能。通过Wav2Lip-HD项目可以快速使用这两种模型&#xff0c;完成高清数字人形象的打造。 项目代码地址&#xff1a;github地址 1.1…

Canal监听MySQL

Canal监听MySQL 1、Mysql数据库开启binlog模式 注意&#xff1a;Mysql容器&#xff0c;此处Mysql版本为5.7 #进入容器 docker exec -it mysql /bin/bash #进入配置目录 cd /etc/mysql/mysql.conf.d #修改配置文件 vi mysqld.cnf(1) 修改mysqld.cnf配置文件&#xff0c;添加如…

Android:安卓开发使用okHttp进行网络请求和MySQL数据库完成图书馆管理系统APP

1、总体目标 1.1 项目概述 项目名称&#xff1a;基于安卓平台的图书管理系统。 本项目旨在研发一个图书管理系统&#xff0c;实现图书馆的信息化管理。在方便用户在线浏览&#xff0c;借阅&#xff0c;归还图书&#xff0c;方便图书馆管理员对图书进行管理。能很好的为用户提…

从零开始理解Linux中断架构(7)--- Linux执行上下文之中断上下文

1 中断处理程序的基本要求 当前运行的loop是一条执行流,中断程序运行开启了另外一条执行流,从上一节得知这是三种跳转的第三类,这个是一个大跳转。对中断程序的基本要求就是中断执行完毕后要恢复到原来执行的程序,除了时间流逝外,原来运行的程序应该毫无感知。 具体到Armv…

如何设计一个短信发送功能

本文主要分享了如何设计一个发送短信功能。 一、总结简述 1.梳理多个平台短信API的发送参数&#xff0c;集成封装提供统一的API&#xff0c;支持多个短信平台&#xff08;阿里云、腾讯云、百度云、京东云、七牛云&#xff09;灵活切换 2.提供存储方案&#xff0c;表结构设计…

Redis数据库操作

Redis 命令参考 — Redis 命令参考http://doc.redisfans.com/ 1、Redis&#xff0c;远程词典服务器&#xff0c;是一个基于内存的键值型NoSQL数据库 特征&#xff1a; 键值型&#xff0c;支持多种不同数据结构&#xff0c;功能丰富 单线程&#xff0c;每个命令具备原子性 …

C语言督学营(中级阶段)

文章目录 中级阶段9.数据结构概述逻辑结构 与 存储结构时间复杂度、空间复杂度 10.11.12.线性表 (代码实战)线性表的定义、特点1.线性表的顺序存储(顺序表示)&#xff1a;顺序表静态分配动态分配顺序表的定义、初始化、插入、删除、按值查找、按位查找 操作 (代码)&#xff1a;…

go开发多云资产管理平台

go开发多云资产管理平台cmdb 代码仓库github.com/yunixiangfeng/gocmdb 云主机管理 主机资源监控 开发流程 Welcome to Beego | Beego bee new gocmdb/servercd gocmdb/servergo mod tidygo get -u github.com/beego/beego/v2 go get -u "github.com/astaxie/beego/o…

津津乐道设计模式 - 模版模式详解(以女友化妆流程带你彻底明白)

&#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Micro麦可乐的博客 &#x1f425;《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程&#xff0c;入门到实战 &#x1f33a;《RabbitMQ》…

JDBC-->java如何连接数据库(详细版小白必备)

个人名片&#xff1a; &#x1f405;作者简介&#xff1a;一名大二在校生&#xff0c;热爱生活&#xff0c;爱好敲码&#xff01; \ &#x1f485;个人主页 &#x1f947;&#xff1a;holy-wangle ➡系列内容&#xff1a; &#x1f5bc;️ tkinter前端窗口界面创建与优化 &…

工业相机——显微镜头/放大镜头

校准尺&#xff0c;最小测量刻度为0.1mm 上图为手机拍的看不清&#xff0c;放了一个网上找的图&#xff0c;校准的详细参数见下图 例如&#xff1a;物距为116mm的显微镜头&#xff0c;这种镜头没有景深&#xff0c;只能测镜头前端到物体116mm的物体 &#xff0c;几乎没有景深&a…

Vscode配置C/C++环境出现报错,导致不能运行代码,报错如下:

Vscode配置C/C环境出现报错&#xff0c;导致不能运行代码&#xff0c;报错如下&#xff1a; 问题描述—gcc : 无法将“gcc”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写&#xff0c;如果包括路径&#xff0c;请确保路径正确&#xff0c;然后再试一次…