代码随想录第52天|300. 最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组

86 阅读2分钟

300. 最长递增子序列

1. first idea

dp[i]表示nums[:i]中最长递增子序列的长度。

我们在第i个位置上选择考虑当前元素和不考虑当前元素进最长递增子序列。

如果当前元素破坏了递增的规则,那么一定不能纳入。 dp[i] = dp[i - 1]

如果当前元素符合递增,那么考虑纳入或不纳入。 dp[i] = max(dp[i - 1] + 1, dp[i - 1])

这个想法是不对的。

2. doc reading

递推式应该是找到j从0到i-1的所有位置对应最长子序列长度dp[j]中,能够纳入nums[i]这个数的,然后将其纳入,并求最大长度。 就是dp[i]

dp[i]=max(dp[j]+1,j[0,i1])dp[i] = max(dp[j] + 1, j\in[0, i -1])
class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        dp = [1] * len(nums)
        max_len = 1
        for i in range(len(dp)):
            for j in range(i):
                if nums[i] > nums[j]:
                    # nums[i]符合条件
                    dp[i] = max(dp[i], dp[j] + 1)
            # dp[i] 现在保存的是包含nums[i]在内数组的最长递增子序列长度
            max_len = max(dp[i], max_len)
        # print(dp)
        return max_len

674. 最长连续递增序列

1. first idea

dp[i]表示包含nums[i]的最长连续递增子序列长度。

遇到不满足递增的nums[i],那么就dp[i]=1. 满足递增nums[i], dp[i] = dp[i - 1] + 1.

最后对整个状态表求最大值即可。

class Solution:
    def findLengthOfLCIS(self, nums: List[int]) -> int:
        dp = [1] * len(nums)
        for idx in range(1, len(nums)):
            if nums[idx] > nums[idx - 1]:
                dp[idx] = dp[idx - 1] + 1
        return max(dp)

718. 最长重复子数组

1. first idea

双层循环。

如果nums1[i]nums1[j]不相同,说明包含当前nums1[i]的子数组与包含nums2[j]的子数组之间不再匹配,dp[i][j]就为0。

否则,dp[i][j]=dp[i - 1][j - 1] + 1

但是我们一开始该怎么赋初始值呢?

2. doc reading

我们给整个dp矩阵的左侧和上侧多加一行0.

这样就能前推了。

class Solution:
    def findLength(self, nums1: List[int], nums2: List[int]) -> int:
        dp = [[0] * (len(nums2) + 1) for _ in range(len(nums1) + 1)]

        max_len = 0
        for i in range(1, len(nums1) + 1):
            for j in range(1, len(nums2) + 1):
                if nums1[i - 1] == nums2[j - 1]:
                    dp[i][j] = dp[i - 1][j - 1] + 1
                max_len = max(dp[i][j], max_len)
        return max_len