【leetcode】热题HOT100

最近又开始刷题了(狗头保命),主要是补之前没做完的。

DP动态规划

152. 乘积最大子序列

给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。

输入: [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。

思路:

用两个dp数组,其中f[i]表示子数组[0, i]范围内的最大子数组乘积,g[i]表示子数组[0, i]范围内的最小子数组乘积,初始化时f[0]和g[0]都初始化为nums[0],其余都初始化为0。那么从数组的第二个数字开始遍历,那么此时的最大值和最小值只会在这三个数字之间产生,即f[i-1]*nums[i],g[i-1]*nums[i],和nums[i]。所以我们用三者中的最大值来更新f[i],用最小值来更新g[i],然后用f[i]来更新结果res即可。

注意负负得正,使用dp_min和dp_max分别保存到i为止连续子序列乘积的最大值和最小值,状态转移公式:

dp_min[i] = min(dp_min[i - 1] * nums[i], dp_max[i - 1] * nums[i], nums[i])
dp_max[i] = max(dp_min[i - 1] * nums[i], dp_max[i - 1] * nums[i], nums[i])
class Solution(object):
    def maxProduct(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums)
        max_list = [0 for _ in range(n)]
        min_list = [0 for _ in range(n)]
        max_list[0] = nums[0]
        min_list[0] = nums[0]
        res = nums[0]
        
        for i in range(1, n):
            max_list[i] = max(max_list[i - 1] * nums[i], max(min_list[i - 1] * nums[i], nums[i]))
            min_list[i] = min(max_list[i - 1] * nums[i], min(min_list[i - 1] * nums[i], nums[i]))
            res = max(res, max_list[i])
        
        return res

494. 目标和

给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S。现在你有两个符号 + 和 -。对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面。

返回可以使最终数组和为目标数 S 的所有添加符号的方法数

输入: nums: [1, 1, 1, 1, 1], S: 3
输出: 5
解释: 

-1+1+1+1+1 = 3
+1-1+1+1+1 = 3
+1+1-1+1+1 = 3
+1+1+1-1+1 = 3
+1+1+1+1-1 = 3

一共有5种方法让最终目标和为3。

思路

class Solution:
    def findTargetSumWays(self, nums: List[int], S: int) -> int:
        sum_n = sum(nums)
        if (sum_n+S)%2!=0 or sum_n<S:
            return 0
        return self.sub_set(nums,(S+sum_n)//2)
        
    def sub_set(self,nums,S):
        dp = [0]*(S+1)
        dp[0] = 1
        for num in nums:
            #每一遍循环得到和值为i的方法数,以次更新
            for i in range(S,num-1,-1):
                dp[i] += dp[i-num]
        return dp[S]
发布了316 篇原创文章 · 获赞 96 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/weixin_31866177/article/details/100149229