300.最长递增子序列
1.dp[i]表示i之前包括i的以nums[i]结尾的最长递增子序列的长度
2.位置i的最长升序子序列等于j从0到i-1各个位置的最长升序子序列 + 1 的最大值。
if (nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1);
// 注意这里不是要dp[i] 与 dp[j] + 1进行比较,而是我们要取dp[j] + 1的最大值。
3. dp[i](即最长递增子序列)起始大小至少都是1.
4. 从前向后遍历
class Solution {
public int lengthOfLIS(int[] nums) {
int n = nums.length;
int[] dp = new int[n];
Arrays.fill(dp,1);
int res = 1;
for(int i=1; i<n; i++){
for(int j=0; j<i; j++){
if(nums[i]>nums[j]){
dp[i] = Math.max(dp[i],dp[j]+1);
}
}
res = Math.max(res,dp[i]);
}
// 注意最长的子序列不一定是在dp[n-1]处
// 所以需要一个res去接收最大的dp值
return res;
}
}
674. 最长连续递增序列
在上一题的基础上要求连续
因此就只需要与前一个比较即可
本题也可用贪心解决
class Solution {
public int findLengthOfLCIS(int[] nums) {
int n = nums.length;
int[] dp = new int[n];
Arrays.fill(dp,1);
int res = 1;
for(int i=1; i<n; i++){
if(nums[i]>nums[i-1]){
dp[i]=dp[i-1]+1;
}
res = Math.max(res,dp[i]);
}
return res;
}
}
// 贪心
class Solution {
public int findLengthOfLCIS(int[] nums) {
int count=1;
int res = 1;
for(int i=1; i<nums.length; i++){
if(nums[i]>nums[i-1]){
count++;
}else{
count=1;
}
res = Math.max(res,count);
}
return res;
}
}
718. 最长重复子数组
1.dp[i][j] :以下标i - 1为结尾的A,和以下标j - 1为结尾的B,最长重复子数组长度。
2.当A[i - 1] 和B[j - 1]相等的时候,dp[i][j] = dp[i - 1][j - 1] + 1;
3.dp[i][0] 和dp[0][j]其实都没有意义,但可以初始化为0。
4.外层for循环遍历A,内层for循环遍历B。
class Solution {
public int findLength(int[] nums1, int[] nums2) {
int m = nums1.length+1;
int n= nums2.length+1;
int res=0;
int[][] dp = new int[m][n];
for(int i=1; i<m; i++){
for(int j=1; j<n; j++){
if(nums1[i-1]==nums2[j-1]){
dp[i][j]=dp[i-1][j-1]+1;
res = Math.max(res,dp[i][j]);
}
}
}
return res;
}
}
1143. 最长公共子序列
1.dp[i][j]:长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列为dp[i][j]
2.递推情况如下
- text1[i - 1] 与 text2[j - 1]相同:dp[i][j] = dp[i - 1][j - 1] + 1;
- text1[i - 1] 与 text2[j - 1]不相同:dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
text1[0, i - 2]与text2[0, j - 1]的最长公共子序列 和 text1[0, i - 1]与text2[0, j - 2]的最长公共子序列,取最大
3.dp[i][0] = 0=dp[0][j]。
4.从前向后,从上到下来遍历
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int m = text1.length()+1;
int n = text2.length()+1;
int[][] dp = new int[m][n];
for(int i=1; i<m; i++){
for(int j=1; j<n; j++){
if(text1.charAt(i-1) == text2.charAt(j-1)){
dp[i][j] = dp[i-1][j-1]+1;
}else{
dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
}
}
}
return dp[m-1][n-1];
}
}
1035. 不相交的线
直线不能相交,就是说明在字符串A中 找到一个与字符串B相同的子序列,且这个子序列不能改变相对顺序。只要相对顺序不改变,连接相同数字的直线就不会相交。
因此,本题说是求绘制的最大连线数,其实就是求两个字符串的最长公共子序列的长度!
与上一题一模一样
class Solution {
public int maxUncrossedLines(int[] nums1, int[] nums2) {
int m = nums1.length+1;
int n = nums2.length+1;
int[][] dp = new int[m][n];
for(int i=1; i<m; i++){
for(int j=1; j<n; j++){
if(nums1[i-1]==nums2[j-1]){
dp[i][j]=dp[i-1][j-1]+1;
}else{
dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
}
}
}
return dp[m-1][n-1];
}
}