day42 动态规划part4 代码随想录算法训练营 416. 分割等和子集
题目:416. 分割等和子集
我的感悟:
- 有点难,
- 更快的解法用了01 True 和False 所以更快
理解难点:
- 转化为背包问题
听课笔记:
代码示例:我优化了下
class Solution:
def canPartition(self, nums: List[int]) -> bool:
if sum(nums) % 2 == 1:
return False
target = sum(nums) // 2
# dp[i]中的i表示背包内总和
# 题目中说:每个数组中的元素不会超过 100,数组的大小不会超过 200
# 总和不会大于20000,背包最大只需要其中一半,所以10001大小就可以了
dp = [0] * (target+1)
# 开始 0-1背包
for i in range(len(nums)):
for j in range(target, nums[i] - 1, -1): # 每一个元素一定是不可重复放入,所以倒序遍历
dp[j] = max(dp[j], dp[j - nums[i]] + nums[i])
if dp[j] == target:
return True
if dp[j] > target:
return False
# 集合中的元素正好可以凑成总和target
# if dp[target] == target:
# return True
return False
通过截图:
扩展写法(这个更快):
class Solution:
def canPartition(self, nums: List[int]) -> bool:
total_sum = sum(nums)
if total_sum % 2 != 0:
return False
target_sum = total_sum // 2
dp = [False] * (target_sum + 1)
dp[0] = True
for num in nums:
# 从target_sum逆序迭代到num,步长为-1
for i in range(target_sum, num - 1, -1):
dp[i] = dp[i] or dp[i - num]
return dp[target_sum]
资料:
- 分割等和子集
本题是 01背包的应用类题目
https://programmercarl.com/0416.%E5%88%86%E5%89%B2%E7%AD%89%E5%92%8C%E5%AD%90%E9%9B%86.html