2024/06/21--代码随想录算法10-12/17| 子序列问题

300.最长递增子序列

力扣链接
在这里插入图片描述

==动规五部曲 ==

  1. dp的定义
    dp[i]表示子序列答案以nums[i]结尾的最长递增子序列的长度
    为什么一定表示 “以nums[i]结尾的最长递增子序” ,因为我们在 做 递增比较的时候,如果比较 nums[j] 和 nums[i] 的大小,那么两个递增子序列一定分别以nums[j]为结尾 和 nums[i]为结尾, 要不然这个比较就没有意义了,不是尾部元素的比较那么 如何算递增呢。
  2. 状态转移方程:
位置i的最长升序子序列等于j从0到i-1各个位置的最长升序子序列 + 1 的最大值。
所以:if (nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1);
  1. dp初始化
    每一个i,对应的dp[i](即最长递增子序列)起始大小至少都是1
  2. 确认遍历顺序:
    dp[i] 是有0到i-1各个位置的最长递增子序列 推导而来,那么遍历i一定是从前向后遍历。
    j其实就是遍历0到i-1,那么是从前到后,还是从后到前遍历都无所谓,只要吧 0 到 i-1 的元素都遍历了就行了。 所以默认习惯 从前向后遍历。
    遍历i的循环在外层,遍历j则在内层

DP

class Solution:def lengthOfLIS(self, nums: List[int]) -> int:if len(nums) <= 1:return len(nums)dp = [1] * len(nums)result = 1for i in range(1, len(nums)):for j in range(0, i):if nums[i] > nums[j]:dp[i] = max(dp[i], dp[j] + 1)result = max(result, dp[i]) #取长的子序列return result

贪心

class Solution:def lengthOfLIS(self, nums: List[int]) -> int:if len(nums) <= 1:return len(nums)tails = [nums[0]]  # 存储递增子序列的尾部元素for num in nums[1:]:if num > tails[-1]:tails.append(num)  # 如果当前元素大于递增子序列的最后一个元素,直接加入到子序列末尾else:# 使用二分查找找到当前元素在递增子序列中的位置,并替换对应位置的元素left, right = 0, len(tails) - 1while left < right:mid = (left + right) // 2if tails[mid] < num:left = mid + 1else:right = midtails[left] = numreturn len(tails)  # 返回递增子序列的长度

674.最长连续递增序列

力扣链接
在这里插入图片描述

==动规五部曲 ==

  1. dp的定义
    dp[i]表示子序列答案以nums[i]结尾的最长递增子序列的长度
  2. 状态转移方程:
if nums[i] > nums[i-1]:     dp[i] = dp[i-1]+1
  1. dp初始化
    每一个i,对应的dp[i](即最长递增子序列)起始大小至少都是1
  2. 确认遍历顺序:
class Solution:def findLengthOfLCIS(self, nums: List[int]) -> int:if len(nums) <= 1:   return len(nums)dp = [1] * len(nums)  #dp[i]表示以nums[i]结尾的子序列的最长连续递增序列res = 1for i in range(1, len(nums)):if nums[i] > nums[i-1]:   #连续记录dp[i] = dp[i-1]+1else: dp[i] = 1res = max(res, dp[i])return res

贪心

class Solution:def findLengthOfLCIS(self, nums: List[int]) -> int:if len(nums) == 0:return 0result = 1 #连续子序列最少也是1count = 1for i in range(len(nums)-1):if nums[i+1] > nums[i]: #连续记录count += 1else: #不连续,count从头开始count = 1result = max(result, count)return result

718.最长重复子数组【公共连续】

力扣链接
在这里插入图片描述

==动规五部曲 ==

  1. dp的定义
    dp[i][j] :以下标i - 1为结尾的A,和以下标j - 1为结尾的B,最长重复子数组长度为dp[i][j]
    (特别注意: 这个公共子字符串是下标i - 1为结尾的A )
  2. 状态转移方程:
 if nums1[i - 1] == nums2[j - 1]:# 在当前位置上的最长公共子数组长度为前一个位置上的长度加一dp[i][j] = dp[i - 1][j - 1] + 1
  1. dp初始化
    dp[i][0] =dp[0][j]=0。
  2. 确认遍历顺序:
class Solution:def findLength(self, nums1: List[int], nums2: List[int]) -> int:# 创建一个二维数组 dp,用于存储最长公共子数组的长度dp = [[0] * (len(nums2) + 1) for _ in range(len(nums1) + 1)]# 记录最长公共子数组的长度result = 0# 遍历数组 nums1for i in range(1, len(nums1) + 1):# 遍历数组 nums2for j in range(1, len(nums2) + 1):# 如果 nums1[i-1] 和 nums2[j-1] 相等if nums1[i - 1] == nums2[j - 1]:# 在当前位置上的最长公共子数组长度为前一个位置上的长度加一dp[i][j] = dp[i - 1][j - 1] + 1# 更新最长公共子数组的长度res = max(res, dp[i][j])# 返回最长公共子数组的长度return result

1143.最长公共子序列【公共子序列】

力扣链接
在这里插入图片描述

==动规五部曲 ==

  1. dp的定义
    dp[i][j]:长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列为dp[i][j]
  2. 状态转移方程:
if (text1[i - 1] == text2[j - 1]) :dp[i][j] = dp[i - 1][j - 1] + 1
else:dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
  1. dp初始化
    dp[i][0] =dp[0][j]=0。
  2. 确认遍历顺序:
class Solution:def longestCommonSubsequence(self, text1: str, text2: str) -> int:# 创建一个二维数组 dp,用于存储最长公共子序列的长度dp = [[0] * (len(text2) + 1) for _ in range(len(text1) + 1)]# 遍历 text1 和 text2,填充 dp 数组for i in range(1, len(text1) + 1):for j in range(1, len(text2) + 1):if text1[i - 1] == text2[j - 1]:# 如果 text1[i-1] 和 text2[j-1] 相等,则当前位置的最长公共子序列长度为左上角位置的值加一dp[i][j] = dp[i - 1][j - 1] + 1else:# 如果 text1[i-1] 和 text2[j-1] 不相等,则当前位置的最长公共子序列长度为上方或左方的较大值dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])# 返回最长公共子序列的长度return dp[len(text1)][len(text2)]

1035.不相交的线【公共子序列】

力扣链接
在这里插入图片描述
本题说是求绘制的最大连线数,其实就是求两个字符串的最长公共子序列的长度!

class Solution:def maxUncrossedLines(self, A: List[int], B: List[int]) -> int:dp = [[0] * (len(B)+1) for _ in range(len(A)+1)]for i in range(1, len(A)+1):for j in range(1, len(B)+1):if A[i-1] == B[j-1]:dp[i][j] = dp[i-1][j-1] + 1else:dp[i][j] = max(dp[i-1][j], dp[i][j-1])return dp[-1][-1]

53.最大子序和

力扣链接
在这里插入图片描述

==动规五部曲 ==

  1. dp的定义
    dp[i]:包括下标i(以nums[i]为结尾)的最大连续子序列和为dp[i]。
  2. 状态转移方程:
        for i in range(1, len(nums)):dp[i] = max(dp[i-1] + nums[i], nums[i]) #状态转移公式
  1. dp初始化
    dp[0] = nums[0]
  2. 确认遍历顺序:
class Solution:def maxSubArray(self, nums: List[int]) -> int:dp = [0] * len(nums)dp[0] = nums[0]result = dp[0]   # res的初始值是dp[0],不是0for i in range(1, len(nums)):dp[i] = max(dp[i-1] + nums[i], nums[i]) #状态转移公式result = max(result, dp[i]) #result 保存dp[i]的最大值return result

392.判断子序列【s在t是否出现】

力扣链接
在这里插入图片描述

==动规五部曲 ==

  1. dp的定义
    dp[i][j]:以i-1为结尾的s子序列中出现以j-1为结尾的t的个数为dp[i][j]。
  2. 状态转移方程:
if s[i-1] == t[j-1]:dp[i][j] = dp[i-1][j-1] + 1
else:dp[i][j] = dp[i][j-1]
  1. dp初始化
    dp[0][0]和dp[i][0]为0
  2. 确认遍历顺序:
class Solution:def isSubsequence(self, s: str, t: str) -> bool:dp = [[0] * (len(t)+1) for _ in range(len(s)+1)]for i in range(1, len(s)+1):for j in range(1, len(t)+1):if s[i-1] == t[j-1]:dp[i][j] = dp[i-1][j-1] + 1else:dp[i][j] = dp[i][j-1]if dp[-1][-1] == len(s):return Truereturn False

115.不同的子序列【s在t出现的个数】

力扣链接
在这里插入图片描述

==动规五部曲 ==

  1. dp的定义
    dp[i][j]:以i-1为结尾的s子序列中,出现以j-1为结尾的t的个数为dp[i][j]。【s[0:i] 中,t[0:j]出现的个数】
  2. 状态转移方程:
if s[i-1] == t[j-1]:dp[i][j] = dp[i-1][j-1] + dp[i-1][j]#1.用上了s[i-1]   2. 没有用上s[i-1],把s[i-1]删掉
else:dp[i][j] = dp[i-1][j]
  1. dp初始化
    dp[0][j]=0
    dp[i][0]:以i-1为结尾的s可以随便删除元素,出现空字符串的个数。
  2. 确认遍历顺序:
class Solution:def numDistinct(self, s: str, t: str) -> int:dp = [[0] * (len(t)+1) for _ in range(len(s)+1)]for i in range(len(s)):dp[i][0] = 1for j in range(1, len(t)):dp[0][j] = 0for i in range(1, len(s)+1):for j in range(1, len(t)+1):if s[i-1] == t[j-1]:dp[i][j] = dp[i-1][j-1] + dp[i-1][j]else:dp[i][j] = dp[i-1][j]return dp[-1][-1]

583. 两个字符串的删除操作

力扣链接
在这里插入图片描述

==动规五部曲 ==

  1. dp的定义
    dp[i][j]:以i-1为结尾的字符串word1,和以j-1位结尾的字符串word2,想要达到相等,所需要删除元素的最少次数。
  2. 状态转移方程:
if word1[i-1] == word2[j-1]:dp[i][j] = dp[i-1][j-1]
else:dp[i][j] = min(dp[i-1][j-1] + 2, dp[i-1][j] + 1, dp[i][j-1] + 1)
  1. dp初始化
    dp[0][j]=j
    dp[i][0]=i
  2. 确认遍历顺序:
class Solution:def minDistance(self, word1: str, word2: str) -> int:dp = [[0] * (len(word2)+1) for _ in range(len(word1)+1)]for i in range(len(word1)+1):dp[i][0] = ifor j in range(len(word2)+1):dp[0][j] = jfor i in range(1, len(word1)+1):for j in range(1, len(word2)+1):if word1[i-1] == word2[j-1]:dp[i][j] = dp[i-1][j-1]else:dp[i][j] = min(dp[i-1][j-1] + 2, dp[i-1][j] + 1, dp[i][j-1] + 1)return dp[-1][-1]
class Solution(object):def minDistance(self, word1, word2):m, n = len(word1), len(word2)# dp 求解两字符串最长公共子序列dp = [[0] * (n+1) for _ in range(m+1)]for i in range(1, m+1):for j in range(1, n+1):if word1[i-1] == word2[j-1]:dp[i][j] = dp[i-1][j-1] + 1else:dp[i][j] = max(dp[i-1][j], dp[i][j-1])# 删去最长公共子序列以外元素return m + n - 2 * dp[-1][-1]

72.编辑距离

力扣链接
在这里插入图片描述

==动规五部曲 ==

  1. dp的定义
    dp[i][j]:以i-1为结尾的字符串word1,和以j-1位结尾的字符串word2,想要达到相等,最小编辑距离为dp[i][j]。。
  2. 状态转移方程:
if word1[i-1] == word2[j-1]:dp[i][j] = dp[i-1][j-1]
else:dp[i][j] = min(dp[i-1][j-1] + 1, dp[i-1][j] + 1, dp[i][j-1] + 1)
  1. dp初始化
    dp[0][j]=j
    dp[i][0]=i
  2. 确认遍历顺序:
class Solution:def minDistance(self, word1: str, word2: str) -> int:dp = [[0] * (len(word2)+1) for _ in range(len(word1)+1)]for i in range(len(word1)+1):dp[i][0] = ifor j in range(len(word2)+1):dp[0][j] = jfor i in range(1, len(word1)+1):for j in range(1, len(word2)+1):if word1[i-1] == word2[j-1]:dp[i][j] = dp[i-1][j-1]else:dp[i][j] = min(dp[i-1][j-1] + 1, dp[i-1][j] + 1, dp[i][j-1] + 1)return dp[-1][-1]

编辑距离总结篇

给定字符串 s 和 t ,判断 s 是否为 t 的子序列。

if (s[i - 1] == t[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1
else:dp[i][j] = dp[i][j - 1]  #相当于t要删除元素,继续匹配

给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数。

if (s[i - 1] == t[j - 1])dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]#一部分是用s[i - 1]来匹配,那么个数为dp[i - 1][j - 1]。#一部分是不用s[i - 1]来匹配,个数为dp[i - 1][j]。
else :dp[i][j] = dp[i - 1][j];

给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最少步数,每步可以删除任意一个字符串中的一个字符。

if (word1[i - 1] == word2[j - 1]) :dp[i][j] = dp[i - 1][j - 1]
else :dp[i][j] = min({dp[i - 1][j - 1] + 2, dp[i - 1][j] + 1, dp[i][j - 1] + 1})

给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所使用的最少操作数 。

if (word1[i - 1] == word2[j - 1]):dp[i][j] = dp[i - 1][j - 1];
else:dp[i][j] = min({dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]}) + 1

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

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

相关文章

【机器学习 复习】第9章 降维算法——PCA降维

一、概念 1.PCA &#xff08;1&#xff09;主成分分析&#xff08;Principal ComponentAnalysis&#xff0c;PCA&#xff09;一种经典的线性降维分析算法。 &#xff08;2&#xff09;原理&#xff0c;这里以二维转一维为例&#xff0c;原来的平面变成了一条直线 这是三维变二…

荷兰与法国战平,双方能携手出现?

就在昨天晚上&#xff0c;荷兰队经历了90分钟的鏖战&#xff0c;最终0-0与法国队握手言和。此役&#xff0c;哈维-西蒙斯为荷兰队打进一球&#xff0c;但进球被判无效。从目前的积分形势来看&#xff0c;双方基本上确定携手晋级16强赛。本场比赛&#xff0c;荷兰队后卫内森-阿克…

GPT 模型简史:从 GPT-1 到 GPT-4

文章目录 GPT-1GPT-2GPT-3从 GPT-3 到 InstructGPTGPT-3.5、Codex 和 ChatGPTGPT-4 GPT-1 2018 年年中&#xff0c;就在 Transformer 架构诞生⼀年后&#xff0c;OpenAI 发表了⼀篇题 为“Improving Language Understanding by Generative Pre-Training”的论文&#xff0c;作者…

告别卡顿,迎接流畅!你的mac电脑清洁利器CleanMyMac一键轻松解决所有问题!

亲爱的CSDN家人们&#xff0c;今天要安利的是一个让无数Mac用户从“抓狂”到“惊喜连连”的小神器—CleanMyMac&#xff01;&#x1f4ab; 如果你还在为电脑的缓慢启动、存储空间告急和莫名其妙的卡顿烦恼&#xff0c;那请跟我一起看看它如何成为你的数字世界里的救星&#xff…

VC++学习(5)——文本编程,插入符的初始化,图形插入符;文字始终在窗口;字符输入功能,回车换行,删除,左键定位;字体修改,字体平滑变色

目录 引出第五讲 文本编程新建项目输入线的初始化根据字体大小定义插入符大小创建图形插入符文字始终保存在窗口中CString类通过字符串资源 路径层字符输入的功能键盘输入消息鼠标左键消息保存点击位置的坐标 输入回车键的处理删除文字的实现 字符输入功能代码字体的修改模拟卡…

Android翻转动画(卡片翻转效果)

前言 最近好友问计蒙翻转动画&#xff0c;恰好在大二那年看Android Api Demo时记了笔记&#xff0c;由此写一篇文章。 需求 屏幕右滑事件触发卡片的翻转效果 &#xff0c;为了方便&#xff0c;在例子中将右滑事件改成按钮点击事件 老规矩&#xff0c;最后有源码 一、先介绍三…

PCL 三次样条插值(二维点)

一、简介 在插值计算中,最简单的分段多项式近似应该是分段线性插值,它由连接一组数据点组成,仅仅只需要将这些点一一用直线进行顺序相连即可。不过线性函数插值的缺点也很明显,就是在两个子区间变化的比较突兀,也就是没有可微性(不够光滑)。因此我们需要更为符合物理情况…

C语言小例程

题目&#xff1a;两个乒乓球队进行比赛&#xff0c;各出三人。甲队为a,b,c三人&#xff0c;乙队为x,y,z三人。已抽签决定比赛名单。有人向队员打听比赛的名单。a说他不和x比&#xff0c;c说他不和x,z比&#xff0c;请编程序找出三队赛手的名单。 #include <stdio.h> #in…

Mac OS 如何在命令行下启动Docker

现象 当用 Mac air作为服务器时&#xff0c;远程登录上去后想使用 docker&#xff0c;却报如下错&#xff1a; Cannot connect to the Docker daemon at unix:///Users/aborn/.docker/run/docker.sock. Is the docker daemon running? 原因分析 因为 docker 有一个守护进程…

外包IT运维解决方案

随着企业信息化进程的不断深入&#xff0c;IT系统的复杂性和重要性日益增加。高效的IT运维服务对于保证业务连续性、提升企业竞争力至关重要。外包IT运维解决方案通过专业的服务和技术支持&#xff0c;帮助企业降低运维成本、提高运维效率和服务质量。 本文结合《外包IT运维解…

教育培训机构寒暑假班学校公众号小程序

&#x1f4da;教育培训学校公众号版本&#xff1a;开启学习新纪元&#x1f680; 一、引言&#xff1a;为何教育培训学校需要公众号版本&#xff1f; 随着数字化时代的来临&#xff0c;传统教育培训行业也在不断探索新的服务模式。公众号作为新媒体平台的一种&#xff0c;具有信…

艾多美用“艾”为生命加油,献血活动回顾

用艾为生命加油 6月10日~16日&#xff0c;艾多美中国开启献血周活动&#xff0c;已经陆续收到来自烟台总部、山东、广东、河南、四川、重庆、贵阳&#xff0c;乌鲁木齐&#xff0c;吉林&#xff0c;等地区的艾多美员工、会员、经销商发来的爱心助力&#xff0c;截止到目前&…

ICP、ISP及IAP烧录介绍

文章目录 不同的程序下载方式一、ICP:In-Circuit Programming二、ISP:In-System Programming三、IAP:In-Application ProgrammingIAP方案设计不同的程序下载方式 目前,单片机的程序烧录方式可以分为三种:ICP、ISP、IAP。 ICP:In Circuit Programing,在电路编程; ISP:…

购买服务器,并安装宝塔

前言&#xff1a; 我们在开发项目时&#xff0c;总会遇到一个问题&#xff0c;就是将我们开发好的项目上传的公网中。对于中小型的项目&#xff0c;我们可以通过购买服务器进行项目的上线。 我们的项目一般是部署在Linux环境中。如果你不是专业的运维人员&#xff0c;可能对于…

考前刷题练手感(北航期末往年数据结构编程题)

本次因为是考前一天极速刷题&#xff0c;所以没有讲解&#xff0c;若有问题可私信。 目录 一、 查找同时空人员二、 老鼠回家-无回路三、函数调⽤关系四、东二食堂模拟五、栈帧 一、 查找同时空人员 【问题描述】 假设一共有6个手机基站&#xff0c;都具有记录手机连接基站状…

天马学航——智慧教务系统(移动端)开发日志八

天马学航——智慧教务系统(移动端)开发日志八 日志摘要&#xff1a;完成了对用户主界面的优化&#xff0c;再次优化数据库缓存&#xff0c;使数据库读写分离 优化主界面 优化用户界面&#xff0c;使界面看起来更加亲切贴合 主要源码 build() {Row() {Column({space:30}) {Te…

调试器接口是什么?

目录 一、调试器接口 1.1 什么是下载调试器&#xff1f; 1.2 JTAG标准/协议 1.3 SWD标准 一、调试器接口 1.1 什么是下载调试器&#xff1f; 简单来讲&#xff0c;它就是一种能把PC端发送的命令&#xff08;通过USB协议&#xff09;转换为MCU能理解的语言&#xff08;SWD协…

# [0622] Task02 model-free 免模型类 RL 算法的预测和控制 【ε 贪心策略 优化的证明】

easy-rl PDF版本 笔记整理 P3 joyrl 比对 补充 P4 - P5 相关 代码 整理 ——> 有空 另开一页 最新版PDF下载 地址&#xff1a;https://github.com/datawhalechina/easy-rl/releases 国内地址(推荐国内读者使用)&#xff1a; 链接: https://pan.baidu.com/s/1isqQnpVRWbb3yh8…

51单片机STC89C52RC——6.1 中断系统

一&#xff0c;文字层面理解 反正我看下面的几段文字时脑壳没有正常运转。一个头几个大 中断系统是为使CPU具有对外界紧急事件的实时处理能力而设置的。 当中央处理机CPU正在处理某件事的时候外界发生了紧急事件请求&#xff0c;要求CPU暂停当前的工作&#xff0c;转而去处理这…

【LLM之KG】KoPA论文阅读笔记

研究背景 知识图谱补全&#xff08;KGC&#xff09;是通过预测知识图谱中缺失的三元组来完善知识图谱的信息。传统方法主要基于嵌入和预训练语言模型&#xff0c;但这些方法往往忽视了知识图谱的结构信息&#xff0c;导致预测效果不佳。 研究目标 本文的研究目标是探索如何将…