代码随想录Day29|动态规划5|动规进阶1|最长连续/不连续

子序列不连续,子数组连续

300. 最长递增子序列

  • nlog(n)时间复杂度的动态规划
  • dp[i] = max(dp[i],dp[j]+1)
class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        dp = [0]*len(nums)
        for i in range(len(nums)):
            for j in range(i):
                if nums[i]>nums[j]:
                    dp[i] = max(dp[i],dp[j]+1)
        return max(dp) + 1  ## 注意返回值

674. 最长连续递增序列

  • 比上题简单,只需记住前一个数字的最长连续数量即可
  • dp[i] = dp[i-1] + 1
class Solution:
    def findLengthOfLCIS(self, nums: List[int]) -> int:
        dp = [1]*len(nums)
        for i in range(1,len(nums)):
            if nums[i]>nums[i-1]:
                dp[i] = dp[i-1] + 1
        return max(dp)

718. 最长重复子数组

  • ** if nums1[i]==nums2[j]: dp[i][j] = dp[i-1][j-1] + 1**
  • dp长度等于数组长度时,在[0,0,0,0,1]和[1,0,0,0,0]这两个用例出错了。是因为没有对i,j进行大于等于1判断,
  • 另外一个解决办法是将dp长度扩展一行一列
class Solution:
    def findLength(self, nums1: List[int], nums2: List[int]) -> int:
        res = 0
        dp = [[0]*len(nums2) for _ in range(len(nums1))]
        for i in range(len(nums1)):
            for j in range(len(nums2)):
                if nums1[i]==nums2[j]:
                    if i>=1 and j>=1:
                        dp[i][j] = dp[i-1][j-1] + 1
                    else:
                        dp[i][j] = 1
                    
                    if dp[i][j]>res:
                        res = dp[i][j]
        return res

1143.最长公共子序列

  • 该题目不要求连续的公共子序列
  • 相等时一定等于对角线+1(肯定大于等于左侧和上侧的数)
  • 不相等时等于max(左侧,上侧)
class Solution:
    def longestCommonSubsequence(self, text1: str, text2: str) -> int:
        dp = [[0]*(len(text2)+1) for _ in range(len(text1)+1)]
        res = 0
        for i in range(len(text1)):
            for j in range(len(text2)):
                if text1[i]==text2[j]:
                    ## 对角线加一一定是大于等于左侧和上侧的数字的
                    # dp[i+1][j+1] = max(dp[i][j+1],dp[i+1][j],dp[i][j] + 1)
                    dp[i+1][j+1] = dp[i][j] + 1
                else:
                    dp[i+1][j+1] = max(dp[i][j+1],dp[i+1][j])
                if res< dp[i+1][j+1]:
                    res =  dp[i+1][j+1]
        return res
        ## 这里其实可以直接返回最后一个值
        # return dp[-1][-1]

1035.不相交的线

  • 题目花里胡哨,其实这个题与1143.最长公共子序列是一样的
class Solution:
    def maxUncrossedLines(self, nums1: List[int], nums2: List[int]) -> int:
        dp = [[0]*(len(nums2)+1) for _ in range(len(nums1)+1)]
        res = 0
        for i in range(len(nums1)):
            for j in range(len(nums2)):
                if nums1[i]==nums2[j]:
                    dp[i+1][j+1] = dp[i][j] + 1
                else:
                    dp[i+1][j+1] = max(dp[i][j+1],dp[i+1][j])
        
        return dp[-1][-1]

53.最大子数组和

  • 之前用过贪心算法,其实简化版动规即贪心
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        dp = nums[0]
        ans = nums[0]
        for i in range(1,len(nums)):
            dp = max(nums[i],dp+nums[i])
            if ans<dp:
                ans = dp
        return ans

1749. 任意子数组和的绝对值的最大值

  • 刚好今天做到的一个题与53.最大子数组和类似,求得是连续子数组的和,这里要求的是绝对值的最大值,因此用两个dp来维护最大和最小即可
class Solution:
    def maxAbsoluteSum(self, nums: List[int]) -> int:
        dp = [0,0]
        res = 0
        for i in nums:
            dp[0] = max(i,dp[0]+i,0)
            dp[1] = min(i,dp[1]+i,0)
            ## 其实改成如下也能AC
            # dp[0] = max(i,dp[0]+i)
            # dp[1] = min(i,dp[1]+i)
            res = max(res,dp[0],abs(dp[1]))
        return res   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值