代码随想录 11.13 || 动态规划 LeetCode 300.最长递增子序列、674.最长连续递增子序列、718.最长重复子数组

300.最长递增子序列

        dp[i] 的意义为,以 nums[i] 为尾元素的数组,其最长递增子序列的长度为 dp[i]。注意,该最长递增子序列不一定包含 nums[i];

        由题目中可知,最长递增子序列不要求在 nums 中连续,递推公式为,在 nums[i] > nums[j] 时,dp[i] = max(dp[i], dp[j] + 1),求当前元素 nums[i] 大于前 i 个元素的最大数量,使用 max() 跳跃继承前面的状态;

        遍历顺序,明显状态 dp[i] 继承自 dp[0 ~ i - 1] 中的某个状态,自前向后遍历;

        dp 数组初始化,全初始化为 1,仅有一个元素时,其最长递增子序列的长度固定为 1;

        在出问题时,打印 dp 数组 debug。

class Solution {
public:
    int lengthOfLIS(vector &nums) {
        int len = nums.size();
        if (len <= 1) return len;

        vector dp(len, 1);

        int result = 0;
        for (int i = 1; i < len; ++i) {
            for (int j = 0; j < i; ++j) {
                if (nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1);
            }
            result = max(result, dp[i]);
        }

        return result;
    }
};

674.最长连续递增子序列

        dp[i] 的意义为,以 nums[i] 为尾元素的数组,其最长连续递增子序列的长度为 dp[i]。注意,该最长递增子序列不一定包含 nums[i];

        由题目中可知,最长连续递增子序列要求在 nums 中连续,递推公式为,在 nums[i] > nums[j] 时,dp[i] = dp[i] + 1。因为要求连续递增,所以不需要跳跃地继承前面的状态,当 nums[i] > nums[i - 1] 时,dp[i] 直接加 1 即可;

        仍然是自前向后遍历;

        dp 数组初始化,全初始化为 1,仅有一个元素时,其最长连续递增子序列的长度固定为 1;

        在出问题时,打印 dp 数组 debug。

class Solution {
public:
    int findLengthOfLCIS(vector &nums) {
        int len = nums.size();
        if (len <= 1) return len;

        vector dp(len, 1);

        int result = 0;
        for (int i = 1; i < len; ++i) {
            if (nums[i] > nums[i - 1]) dp[i] = dp[i - 1] + 1;
            result = max(result, dp[i]);
        }

        return result;
    }
};

718.最长重复子数组

        给两个整数数组 nums1 和 nums,返回两个数组中 公共的、最长的 子数组的长度。

        dp[i][j] 的意义为,在 nums1 中以下标 i - 1为结尾的子数组,在 nums2 中以下标 j - 1 为结尾的子数组,二者公共的、最长的子数组的长度为 dp[i][j];

        递推公式,当 nums[i - 1] == nums[j - 1] 时,dp[i][j] = dp[i - 1][j - 1] + 1。如果当前在 nums1 中访问的元素,和在 nums2 中访问的元素相同,则在该下标处的最长重复子数组的长度为此前的状态加 1。很好理解,如果当前相同,就将此前的状态加 1 作为现在的状态;

        遍历顺序,从前向后;

        dp 数组初始化,根据我们对 dp 数组的定义,二维 dp 数组的第一行和第一列均无意义,因为 dp[1][1] 表示 nums1[0] 和 nums2[0] 是否相同,为第一个访问的元素对。因此将第一行和第一列全初始化为 0 即可;

        在发生问题时,打印 dp 数组 debug。

class Solution {
public:
    int findLength(vector &nums1, vector &nums2) {
        auto dp = vector> (nums1.size() + 1, vector(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(result, dp[i][j]);
            }
        }

        return result;
    }
};

你可能感兴趣的:(leetcode,动态规划,算法)