文章链接: 300.最长递增子序列 674. 最长连续递增序列 718. 最长重复子数组

视频链接: 300.最长递增子序列 674. 最长连续递增序列 718. 最长重复子数组

题目链接: 300.最长递增子序列 674. 最长连续递增序列 718. 最长重复子数组


300.最长递增子序列

思路:

1.dp数组的含义:dp[i]表示i之前包括i的 以nums[i]结尾 的最长递增子序列的长度;

2.递推公式if (nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1);

3.初始化dp数组最长递增子序列最小也为dp[i] = 1;


class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        vector<int> dp(nums.size() + 1, 1);
        int result = 0;
        for (int i = 0; i < nums.size(); i++) {
            for (int j = 0; j < i; j++) {
                if (nums[i] > nums[j]) { // 严格递增
                    dp[i] = max(dp[j] + 1, dp[i]); // + 1指的是加nums[i]
                }
            }
            result = max(result, dp[i]);
        }
        return result;
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.


674.最长连续递增序列

思路:

与上一题的区别:该题要求是 连续 的递增子序列;只需比较nums[i]和nums[i - 1];


1.dp数组的含义:dp[i]表示i之前包括i的 以nums[i]结尾 的最长连续递增子序列的长度;

2.递推公式if (nums[i] > nums[i - 1]) dp[i] = max(dp[i], dp[i - 1] + 1);

3.初始化dp数组最长递增子序列最小也为dp[i] = 1;


class Solution {
public:
    int findLengthOfLCIS(vector<int>& nums) {
        vector<int> dp(nums.size() + 1, 1);
        int result = 1;
        for (int i = 1; i <nums.size(); i++) {
            if (nums[i] > nums[i - 1]) {
                dp[i] = max(dp[i], dp[i - 1] + 1);
            }
            result = max(result, dp[i]);
        }
        return result;
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.


718.最长重复子数组

思路:

1.dp数组的含义

dp[i][j] :以下标i - 1为结尾的A,和以下标j - 1为结尾的B,最长重复子数组长度为dp[i][j]。

问:为什么不能“以下标i为结尾的A,和以下标j为结尾的B,最长重复子数组长度为dp[i][j]。”?

答:因为如果按照问题中的这种定义方法,那么初始化数组时很麻烦,要单独处理初始化的部分;而用第一种定义的方法,就可以直接将dp[i][0] 和 dp[0][j]初始化成0;

2.递推公式if (nums1[i - 1] == nums2[j - 1])   dp[i][j] = dp[i - 1][j - 1] + 1;

3.初始化dp数组dp[i][0] 和dp[0][j]要初始化为0。


// 二维数组
class Solution {
public:
    int findLength(vector<int>& nums1, vector<int>& nums2) {
        vector<vector<int>> dp(nums1.size() + 1, vector<int> (nums2.size() + 1, 0));
        int result = 0;
        for (int i = 1; i <= nums1.size(); i ++) {
            for (int j = 1; j <= nums2.size(); j++) {
                if (nums1[i - 1] == nums2[j - 1]) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                }
                result = max(dp[i][j], result);
            }
        }
        return result;
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
// 一维(滚动)数组(小白不必掌握)

// dp[i][j]都是由dp[i - 1][j - 1]推出。那么压缩为一维数组,也就是dp[j]都是由dp[j - 1]推出。
// 也就是相当于可以把上一层dp[i - 1][j]拷贝到下一层dp[i][j]来继续用。

class Solution {
public:
    int findLength(vector<int>& nums1, vector<int>& nums2) {
        vector<int> dp(vector<int>(nums2.size() + 1, 0));
        int result = 0;
        for (int i = 1; i <= nums1.size(); i++) {
            for (int j = nums2.size(); j > 0; j--) {
                if (nums1[i - 1] == nums2[j - 1]) {
                    dp[j] = dp[j - 1] + 1;
                } else dp[j] = 0; // 注意:不相等的时候要有赋0的操作
                if (dp[j] > result) result = dp[j];
            }
        }
        return result;
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.