力扣每日一题(五十九——(线性)动态规划)

仅以此纪录LeetCode所刷题目。

题目描述:

示例:

思路:

本题使用动态规划的方法去求解,我们首先建立一个dp数组,之后进行双层的for循环,dp数组中存储的是在当前位置下最长的递增子序列的长度,之后我们返回dp数组的最大值即可。

代码:

class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        list1 = [1] * len(nums)
        for i in range(len(nums)):
            for j in range(i):
                if nums[i] > nums[j]:
                    list1[i] = max(list1[j]+1,list1[i])
        return max(list1)

 题目描述:

示例:

思路:

这道题时最长子序列的复杂版,我们仍然是使用动态规划的方法,唯一不同的是我们需要再次定义一个数组里面装的是最长子序列的个数。如下的代码上会有提到。

代码:

class Solution:
    def findNumberOfLIS(self, nums: List[int]) -> int:
        n, max_len, ans = len(nums), 0, 0
        dp = [0] * n
        cnt = [0] * n
        for i, x in enumerate(nums):
            dp[i] = 1
            cnt[i] = 1
            for j in range(i):
                if x > nums[j]:
                    if dp[j] + 1 > dp[i]:
                        dp[i] = dp[j] + 1
                        cnt[i] = cnt[j]  # 重置计数
                    elif dp[j] + 1 == dp[i]:
                        cnt[i] += cnt[j]
            if dp[i] > max_len:
                max_len = dp[i]
                ans = cnt[i]  # 重置计数
            elif dp[i] == max_len:
                ans += cnt[i]
        return ans

题目描述:

示例:

思路:

这道题的思路和之前做的一个长方形嵌套是比较像的,只是这题比较严格,只有信封的宽度和高度都大的时候才能装得下。首先我们进行排序,我们首先按照envelops[0]升序,再按照envelops[1]降序,之后我们遍历envelopes数组是只需要判断envelops[1]即可,因为我们已经按照按照envelops[1]降序排列,因此如果遇到更大的envelops[1]那么就只有可能是envelops[0]已经改变,这样的情况表示可以装下信封,如果遇到比较小的envelops[1],我们是用二分法将其插入即可,最后返回数组的长度即为答案。

代码:

class Solution:
    def maxEnvelopes(self, envelopes: List[List[int]]) -> int:
        if not envelopes:
            return 0
        n = len(envelopes)
        envelopes = sorted(envelopes,key = lambda a : (a[0] , -a[1]))
        f = [envelopes[0][1]]
        for i in range(1,n):
            num = envelopes[i][1]
            if num > f[-1]:
                f.append(num)
            else:
                a = bisect.bisect_left(f,num)
                f[a] = num
        return len(f)

题目描述:

示例: 

思路:

这道题属于比较经典的动态规划问题,我们只需要在原数组上进行操作即可。遍历数组,判断nums[i-1] + nums[i] 和 nums[i] 的大小关系,如果我们发现 nums[i-1] + nums[i] > nums[i],那么nums[i] = nums[i-1] + nums[i] ,反之不进行任何操作直接继续进行遍历。

代码:

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        for i in range(1,len(nums)):
            nums[i] = max(nums[i-1] + nums[i],nums[i])
        return max(nums)

题目描述:

示例:

思路:

这道题我们首先要知道一点,最小的数*负数 可能会变成 最大的数,最大的数*负数 可能会变成 最小的数,因此本题我们不仅要存储当前乘积最大的数,还要存储当前乘积最小的数。在遍历的时候每次都要更新这两个数,同时也要更新我们将要返回的结果(最大值)。

代码: 

class Solution:
    def maxProduct(self, nums: List[int]) -> int:
        if not nums:
            return 0
        cur_max = nums[0]
        cur_min = nums[0]
        res = nums[0]
        for i in range(1,len(nums)):
            now_max = max(cur_max * nums[i],cur_min * nums[i],nums[i])
            now_min = min(cur_min * nums[i],cur_max * nums[i],nums[i])
            res = max(res,now_max)
            cur_max = now_max
            cur_min = now_min
        return res

题目描述:

示例:

思路:

本题有一个巧妙地算法,读题之后我们应该直到如果出现最大连续子数字会出现两种情况,一种是该子数组出现在数组里面,另外一种情况是该数组结尾+该数组开头为最大子数组,因此如果是第一种情况,我们之前的题目中提到过,如果是第二种情况,那么我们可以用整个数组的和-最小子数组。(要特殊讨论数组元素全为负数的情况)

代码:

class Solution:
    def maxSubarraySumCircular(self, nums: List[int]) -> int:
        count = 0
        count_1 = 0
        for num in nums:
            count += num
            if num < 0:
                count_1 += 1
        if count_1 == len(nums):
            return max(nums)
        nums1 = nums.copy()
        for i in range(1,len(nums1)):
            nums1[i] = max(nums1[i-1] + nums1[i],nums1[i])
        max_nums = max(nums1)
        for i in range(1,len(nums)):
            nums[i] = min(nums[i-1] + nums[i],nums[i])
        return max(max_nums,count - min(nums))

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值