最长递增子序列
题目:给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。
例如:
输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。
Solution:
Step 1: dp[i]表示i之前包括i的最长上升子序列。
Step 2: 状态转移方程:
if (nums[i] > nums[j])
dp[i] = max(dp[i], dp[j] + 1);
其中,j 的范围是(0,i-1).
Step 3: 初始化:每一个i,对应的dp[i]起始大小至少都是是1.
Step 4: 遍历顺序:
dp[i] 是由0到i-1各个位置的最长升序子序列推导而来,那么遍历i一定是从前向后遍历。
Step 5: 敲代码
int lengthOfLIS(vector<int>& nums) {
if (nums.size() <= 1)
return nums.size();
vector<int> dp(nums.size(), 1);
int result = 0; //维持最长的子序列
for (int i = 1; i < nums.size(); i++) {
for (int j = 0; j < i; j++) {
if (nums[i] > nums[j])
dp[i] = max(dp[i], dp[j] + 1);
}
if (dp[i] > result)
result = dp[i]; // 取长的子序列
}
return result;
}
最长连续递增子序列
题目:给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。
例如:
输入:nums = [1,3,5,4,7]
输出:3
解释:最长连续递增序列是 [1,3,5], 长度为3。
尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为 5 和 7 在原数组里被 4 隔开。
Solution:
Step 1: dp[i]: 以下标i为结尾的数组的连续递增的子序列长度为dp[i]。
Step 2: 递推公式:
if nums[i + 1] > nums[i],那么以 i+1 为结尾的数组的连续递增的子序列长度 一定等于 以i为结尾的数组的连续递增的子序列长度 + 1 。
也就是说:
if (nums[i+1]>nums[i]) dp[i+1]=dp[i]+1;
Step 3: 初始化:
以下标i为结尾的数组的连续递增的子序列长度最少也应该是1,即就是nums[i]这一个元素。所以dp[i]应该初始1;
Step 4: 敲代码
int findLengthOfLCIS(vector<int>& nums) {
if (nums.size() == 0)
return 0;
int result = 1;
vector<int> dp(nums.size()+1,1);
for (int i = 0; i < nums.size() - 1; i++) {
if (nums[i + 1] > nums[i]) { // 连续记录
dp[i + 1] = dp[i] + 1;
}
if (dp[i + 1] > result)
result = dp[i + 1];
}
return result;
}
最长重复子数组
给两个整数数组 A 和 B ,返回两个数组中公共的、长度最长的子数组的长度。
例如:
输入:A: [1,2,3,2,1] B: [3,2,1,4,7]
输出:3
解释:长度最长的公共子数组是 [3, 2, 1] 。
Solution :
Step 1: dp[i][j] :以下标i - 1为结尾的A,和以下标j - 1为结尾的B,最长重复子数组长度为dp[i][j]。
Step 2: dp[i][j]的状态只能由dp[i - 1][j - 1]推导出来。即当A[i - 1] 和B[j - 1]相等的时候,dp[i][j] = dp[i - 1][j - 1] + 1;根据递推公式可以看出,遍历i 和 j 要从1开始.
Step 3: 由dp[i][j]的定义,dp[i][0] 和dp[0][j]其实都是没有意义的,但dp[i][0] 和dp[0][j]要初始值,因为 为了方便递归公式dp[i][j] = dp[i - 1][j - 1] + 1;
所以dp[i][0] 和dp[0][j]初始化为0。
Step 4: 敲代码
int findLength(vector<int>& A, vector<int>& B) {
vector<vector<int>> dp (A.size() + 1, vector<int>(B.size() + 1, 0));
int result = 0;
for (int i = 1; i <= A.size(); i++) {
for (int j = 1; j <= B.size(); j++) {
if (A[i - 1] == B[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
}
if (dp[i][j] > result)
result = dp[i][j];
}
}
return result;
最长公共子序列
题目:给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列的长度。
例如:
输入:text1 = “abcde”, text2 = “ace”
输出:3
解释:最长公共子序列是 “ace”,它的长度为 3。
Step 1: dp[i][j]:长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列为dp[i][j].
Step 2: if text1[i - 1] 与 text2[j - 1]相同,那么找到了一个公共元素,所以dp[i][j] = dp[i - 1][j - 1] + 1; if text1[i - 1] 与 text2[j - 1]不相同,那就看看text1[0, i - 2]与text2[0, j - 1]的最长公共子序列 和 text1[0, i - 1]与text2[0, j - 2]的最长公共子序列,取最大的。就是dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
Step 3:
dp[i][0] = 0, dp[0][j]也是0。
Step 4: 敲代码
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 - 1][j], dp[i][j - 1]);
}
}
}
return dp[text1.size()][text2.size()];
}