最近又开始刷题了(狗头保命),主要是补之前没做完的。
DP动态规划
给定一个整数数组 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
给定一个非负整数数组,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]