子序列就是在一个数组中按顺序挑选若干数,子数组是连续的子序列,视为特殊的子序列问题
300. 最长递增子序列 - 力扣(LeetCode)https://leetcode.cn/problems/longest-increasing-subsequence/description/
class Solution {
public:
//dp[i]是以nums[i]结尾的最长严格递增子序列的长度
int lengthOfLIS(vector& nums) {
int n=nums.size();
vector dp(n,1);
int max1=1;
for(int i=1;i nums[j])
{
dp[i]=max(dp[i],dp[j]+1);
max1=max(max1,dp[i]);
}
}
}
return max1;
}
};
674. 最长连续递增序列 - 力扣(LeetCode)674. 最长连续递增序列 - 给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。连续递增的子序列 可以由两个下标 l 和 r(l < r)确定,如果对于每个 l <= i < r,都有 nums[i] < nums[i + 1] ,那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]] 就是连续递增子序列。 示例 1:输入:nums = [1,3,5,4,7]输出:3解释:最长连续递增序列是 [1,3,5], 长度为3。尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为 5 和 7 在原数组里被 4 隔开。 示例 2:输入:nums = [2,2,2,2,2]输出:1解释:最长连续递增序列是 [2], 长度为1。 提示: * 1 <= nums.length <= 104 * -109 <= nums[i] <= 109https://leetcode.cn/problems/longest-continuous-increasing-subsequence/
class Solution {
public:
//dp[j] 表示以j结尾的连续递增子序列长度
//递推公式
int findLengthOfLCIS(vector& nums) {
int n=nums.size();
int maxAns=1;
vector dp(n,1);
for(int i=1;inums[i-1]) {
dp[i]=dp[i-1]+1;
if(dp[i]>maxAns) maxAns=dp[i];
}
}
return maxAns;
}
};
class Solution {
public:
//dp[j] 表示以j结尾的连续递增子序列长度
//递推公式
int findLengthOfLCIS(vector& nums) {
int n=nums.size();
int l,r=1;
int maxlen=1;
for(l=0;lnums[r-1])
{
maxlen=max(maxlen,r-l+1);
r++;
}
//这个重置状态你得想一下
l=r-1;r=r+1;
}
return maxlen;
}
};
718. 最长重复子数组 - 力扣(LeetCode)https://leetcode.cn/problems/maximum-length-of-repeated-subarray/description/
class Solution {
public:
int findLength(vector& nums1, vector& nums2) {
//子数组是连续子序列
int sizeA=nums1.size();
int sizeB=nums2.size();
int max=0;
//dp[i][j]的含义是nums1第i个数结尾的子数组和nums2第j个数结束的子数组公共的最大长度
vector> dp(sizeA+1,vector(sizeB+1,0));
for(int i=1;i<=sizeA;i++)
{
for(int j=1;j<=sizeB;j++)
{
if(nums1[i-1]==nums2[j-1])
{
dp[i][j]=dp[i-1][j-1]+1;
if(dp[i][j]>=max)
{
max=dp[i][j];
}
}
}
}
return max;
}
};
1143. 最长公共子序列 - 力扣(LeetCode)https://leetcode.cn/problems/longest-common-subsequence/description/
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
//dp[i][j]表示以text1以i-1结尾,text2以j-1结尾的公共子序列最长长度
int size1=text1.size();
int size2=text2.size();
vector>dp(size1+1,vector(size2+1,0));
for(int i=1;i<=size1;i++)
{
for(int j=1;j<=size2;j++)
{
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]);
}
}
}
return dp[size1][size2];
}
};
1035. 不相交的线 - 力扣(LeetCode)https://leetcode.cn/problems/uncrossed-lines/description/这题实际上就是求一个最长公共子序列
class Solution {
public:
int maxUncrossedLines(vector& nums1, vector& nums2) {
int size1=nums1.size(),size2=nums2.size();
vector>dp(size1+1,vector(size2+1,0));
for(int i=1;i<=size1;i++)
{
for(int j=1;j<=size2;j++)
{
if(nums1[i-1]==nums2[j-1])
{
dp[i][j]=dp[i-1][j-1]+1;
}
else
{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
}
return dp[size1][size2];
}
};
53. 最大子数组和 - 力扣(LeetCode)https://leetcode.cn/problems/maximum-subarray/
class Solution {
public:
int maxSubArray(vector& nums) {
if (nums.size() == 0) return 0;
vector 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;
}
};
392. 判断子序列 - 力扣(LeetCode)https://leetcode.cn/problems/is-subsequence/description/
class Solution {
public:
bool isSubsequence(string s, string t) {
int n = s.length(), m = t.length();
int i = 0, j = 0;
while (i < n && j < m) {
if (s[i] == t[j]) {
i++;
}
j++;
}
return i == n;
}
};
判断最长公共子序列长度和t的大小是否相等
class Solution {
public:
bool isSubsequence(string s, string t) {
//实际上就是最长公共子序列,如果这个最长公共子序列的长度是s的长度,则是
int n = s.length(), m = t.length();
//dp[i][j] 表示以j结尾的子数组 是以i结尾的字串,相同子序列的长度
vector> dp(n+1,vector(m+1,false));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(s[i-1]==t[j-1])
{
dp[i][j]=dp[i-1][j-1]+1;
}
else
{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
}
//最长公共子序列dp[i-1][j],dp[i][j-1]
return dp[n][m]==s.size();
}
};
class Solution {
public:
bool isSubsequence(string s, string t) {
int len1=s.size();
int len2=t.size();
vector> dp(len1+1,vector(len2+1));
//s是待匹配,j是大的
//dp[i][j]的含义是s以i结尾的字符串是不是t以j结尾的字符串的字串
for(int j=0;j<=len2;j++)
{
dp[0][j]=1;
}
for(int i=1;i<=len1;i++)
{
for(int j=1;j<=len2;j++)
{
if(s[i-1]==t[j-1])
{
dp[i][j]=dp[i-1][j-1]||dp[i][j-1];
}
else
{
dp[i][j]=dp[i][j-1];
}
}
}
return dp[len1][len2];
}
};
583. 两个字符串的删除操作 - 力扣(LeetCode)https://leetcode.cn/problems/delete-operation-for-two-strings/
class Solution {
public:
int minDistance(string word1, string word2)
{
//dp[i][j]表示word1以i结尾和word2以j结尾的最小步数
int len1=word1.size(),len2=word2.size();
vector> dp(len1+1,vector(len2+1));
for(int i=0;i<=len1;i++)
{
dp[i][0]=i;
}
for(int j=0;j<=len2;j++)
{
dp[0][j]=j;
}
for(int i=1;i<=len1;i++)
{
for(int j=1;j<=len2;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],dp[i][j-1])+1;
}
}
}
return dp[len1][len2];
}
};
72. 编辑距离 - 力扣(LeetCode)https://leetcode.cn/problems/edit-distance/
class Solution {
public:
int minDistance(string word1, string word2) {
//dp[i][j]的含义是把word1以i结尾的子串转化成word2以j结尾的字串的最少操作数
int len1=word1.size();
int len2=word2.size();
vector>dp(len1+1,vector(len2+1,0));
for(int i=0;i<=len1;i++)
{
dp[i][0]=i;
}
for(int j=0;j<=len2;j++)
{
dp[0][j]=j;
}
for(int i=1;i<=len1;i++)
{
for(int j=1;j<=len2;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],dp[i][j-1]);
dp[i][j]=min(dp[i][j],dp[i-1][j-1]);
dp[i][j]+=1;
}
}
}
return dp[len1][len2];
}
};