53. 最大子序和 392.判断子序列 115.不同的子序列 583. 两个字符串的删除操作 72. 编辑距离

编程入门 行业动态 更新时间:2024-10-25 09:35:20

53. 最大子序和 392.判断子<a href=https://www.elefans.com/category/jswz/34/1769864.html style=序列 115.不同的子序列 583. 两个字符串的删除操作 72. 编辑距离"/>

53. 最大子序和 392.判断子序列 115.不同的子序列 583. 两个字符串的删除操作 72. 编辑距离

53. 最大子序和 

题目:

给定一个整数数组,求最大连续子序列和。(至少包含一个元素)

示例:

  • 输入: [-2,1,-3,4,-1,2,1,-5,4]
  • 输出: 6
  • 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6
  • 意为为了连续最大负数都可以包含进来。

dp数组含义:

dp[i]:包括下标i(以nums[i]为结尾)的最大连续子序列和为dp[i]

class Solution {
public:int maxSubArray(vector<int>& nums) {if (nums.size() == 0) return 0;vector<int> dp(nums.size());dp[0] = nums[0];int result = dp[0];for (int i = 1; i < nums.size(); i++) {dp[i] = max(dp[i - 1] + nums[i], nums[i]); // 状态转移公式if (dp[i] > result) result = dp[i]; // result 保存dp[i]的最大值}return result;}
};

 用递推公式 dp[i] = max(dp[i - 1] + nums[i], nums[i])推导可以看出,若上一步的dp值加上当前遍历的nums值 大于 当前遍历的nums值,则取dp[i - 1] + nums[i],否则取nums[i]。

这样可以保证连续的值一直是最大值,不符和就从当前的nums值重新开始。

  392.判断子序列

题目:

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

字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。

dp数组含义:

dp[i][j] 表示以下标i-1为结尾的字符串s,和以下标j-1为结尾的字符串t,相同子序列的长度为dp[i][j]

class Solution {
public:bool isSubsequence(string s, string t) {vector<vector<int>> dp(s.size() + 1, vector<int>(t.size() + 1, 0));for (int i = 1; i <= s.size(); i++) {for (int j = 1; j <= t.size(); j++) {if (s[i - 1] == t[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;else dp[i][j] = dp[i][j - 1];}}if (dp[s.size()][t.size()] == s.size()) return true;return false;}
};

115.不同的子序列 

题目:

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

dp数组含义:

dp[i][j]:以i-1为结尾的s子序列中出现以j-1为结尾的t的个数为dp[i][j]。

class Solution {
public:int numDistinct(string s, string t) {vector<vector<uint64_t>> dp(s.size() + 1, vector<uint64_t>(t.size() + 1));for (int i = 0; i < s.size(); i++) dp[i][0] = 1;for (int j = 1; j < t.size(); j++) dp[0][j] = 0;for (int i = 1; i <= s.size(); i++) {for (int j = 1; j <= t.size(); j++) {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[s.size()][t.size()];}
};

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

题目:

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

  • 输入: "sea", "eat"
  • 输出: 2
  • 解释: 第一步将"sea"变为"ea",第二步将"eat"变为"ea

dp数组含义:

dp[i][j]:以i-1为结尾的字符串word1,和以j-1位结尾的字符串word2,想要达到相等,所需要删除元素的最少次数。

class Solution {
public:int minDistance(string word1, string word2) {vector<vector<int>> dp(word1.size() + 1, vector<int>(word2.size() + 1));for (int i = 0; i <= word1.size(); i++) dp[i][0] = i;for (int j = 0; j <= word2.size(); j++) dp[0][j] = j;for (int i = 1; i <= word1.size(); i++) {for (int j = 1; j <= word2.size(); j++) {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[word1.size()][word2.size()];}
};

看见了最左上角的右边和下边从0开始赋值的初始化1...n

字符匹配dp[i][j] = dp[i - 1][j - 1];字符不匹配  dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1);

最后结果依照dp数组定义,返回最右下角值

递推公式;

  • 当word1[i - 1] 与 word2[j - 1]相同的时候
  • 当word1[i - 1] 与 word2[j - 1]不相同的时候

当word1[i - 1] 与 word2[j - 1]相同的时候,dp[i][j] = dp[i - 1][j - 1];

当word1[i - 1] 与 word2[j - 1]不相同的时候,有三种情况:

情况一:删word1[i - 1],最少操作次数为dp[i - 1][j] + 1

情况二:删word2[j - 1],最少操作次数为dp[i][j - 1] + 1

情况三:同时删word1[i - 1]和word2[j - 1],操作的最少次数为dp[i - 1][j - 1] + 2

取最小值递推公式:dp[i][j] = min({dp[i - 1][j - 1] + 2, dp[i - 1][j] + 1, dp[i][j - 1] + 1});

初始化:

从递推公式 dp[i][j] = min(dp[i - 1][j - 1] + 2, min(dp[i - 1][j], dp[i][j - 1]) + 1); 和dp[i][j] = dp[i - 1][j - 1]可以看出dp[i][j]都是根据左上方、正上方、正左方推出来的。(同时遍历顺序也要求左到右,上到下,包装存在这些值)

所以dp[i][0] 和 dp[0][j]一定要初始化的。

一边单词为0的字符串,另一边要怎么删才相等呢,当然是有多少删多少,一个为i,一个为j

vector<vector<int>> dp(word1.size() + 1, vector<int>(word2.size() + 1));
for (int i = 0; i <= word1.size(); i++) dp[i][0] = i;
for (int j = 0; j <= word2.size(); j++) dp[0][j] = j;

 72. 编辑距离 

题目:

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

你可以对一个单词进行如下三种操作:

  • 插入一个字符

  • 删除一个字符

  • 替换一个字符

  • 示例 2:

  • 输入:word1 = "intention", word2 = "execution"

  • 输出:5

  • 解释: intention -> inention (删除 't') inention -> enention (将 'i' 替换为 'e') enention -> exention (将 'n' 替换为 'x') exention -> exection (将 'n' 替换为 'c') exection -> execution (插入 'u')

dp数组含义:

dp[i][j] 表示以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dp[i][j]。

 

递推公式:

dp[i][j]由4种情况推出,

if (word1[i - 1] == word2[j - 1])不操作
if (word1[i - 1] != word2[j - 1])增删换

word1[i - 1] == word2[j - 1]时

不操作:dp[i][j] = dp[i - 1][j - 1];这里就是匹配成功不用操作的意思(继承之前的操作次数

word1[i - 1]  != word2[j - 1]时

  • 删除:dp[i][j] = dp[i - 1][j] + 1;

操作数+1,忽略当前值,继续遍历寻找匹配值

  • 增加:dp[i][j] = dp[i][j - 1] + 1;

这里的删除相当于增加,word2添加一个元素,相当于word1删除一个元素

例如 word1 = "ad" ,word2 = "a"word1删除元素'd' 和 word2添加一个元素'd'的操作数都是1,由于求的也是操作数,所以,增加word1一次相当于删除word2一次

所以增加公式:dp[i][j] = dp[i][j - 1] + 1;

  • 换改:dp[i][j] = dp[i - 1][j - 1];

换改后,word1[i - 1] 和word2[j - 1]从不相等变成了相等,所以用 dp[i][j] = dp[i - 1][j - 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], dp[i - 1][j], dp[i][j - 1]}) + 1;
}

初始化: 

dp[i][j]的定义:

dp[i][j] 表示以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dp[i][j]

dp[i][0] :以下标i-1为结尾的字符串word1,和空字符串word2,最近编辑距离为dp[i][0]。

那么dp[i][0]就应该是i,对word1里的元素全部做删除操作,即:dp[i][0] = i;

同理dp[0][j] = j;

for (int i = 0; i <= word1.size(); i++) dp[i][0] = i;
for (int j = 0; j <= word2.size(); j++) dp[0][j] = j;

 遍历顺序:

由图可看出,递推公式依赖关系。即从左到右从上到下去遍历。

总代码:

class Solution {
public:int minDistance(string word1, string word2) {vector<vector<int>> dp(word1.size() + 1, vector<int>(word2.size() + 1, 0));for (int i = 0; i <= word1.size(); i++) dp[i][0] = i;for (int j = 0; j <= word2.size(); j++) dp[0][j] = j;for (int i = 1; i <= word1.size(); i++) {for (int j = 1; j <= word2.size(); j++) {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;}}}return dp[word1.size()][word2.size()];}
};

115和583被吞了。

更多推荐

53. 最大子序和 392.判断子序列 115.不同的子序列 583. 两个字符串的删除操作 72. 编辑距离

本文发布于:2023-11-15 08:12:09,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1596485.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:序列   大子   字符串   距离   编辑

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!