给你一个 只包含正整数 的 非空 数组 nums
。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
示例 1:
输入:nums = [1,5,11,5] 输出:true 解释:数组可以分割成 [1, 5, 5] 和 [11] 。
示例 2:
输入:nums = [1,2,3,5] 输出:false 解释:数组不能分割成两个元素和相等的子集。
思路:如果这两个子集的和没别是sun(nums)的一半,则返回True。反之,则为False。
仍然参考了代码随想录的方法。
【方法一】回溯法,找到所有的子集(时间复杂度高,最终超出时间限制)
def canPartition(nums):
result = []
sum_num = sum(nums)
if sum_num%2!=0:
return False
else:
target = sum_num/2
def backtracking(path,remaining):
result.append(path)
for i in range(len(remaining)):
backtracking(path+[remaining[i]],remaining[i+1:])
backtracking([],nums)
for j in result:
if sum(j) == target:
return True
return False
【方法二】动态规划 0-1背包问题
这里num既是重量 又是价值
Step1: 确定dp[j]的含义
j为背包的容量 dp[j] 背包最大的价值
所以最终的目标是dp[target] == target
Step2: 递推公式
dp[j] = max(dp[j],dp[j-num]+num)
为什么这里是dp[j],因为该公式是由二维递推公式压缩得来的
Step3: dp数组如何初始化
dp = [0]*(target+1)
为什么是target+1,假设dp = [0]
Step4:遍历顺序
先遍历物品,再遍历背包(倒序遍历)
for num in nums:
for j in range(target,num-1,-1)
为什么是从target到num-1,因为背包容量小于num(即为重量)的话没有意义
Step5:打印dp数组
return dp[target] == target
class Solution(object):
def canPartition(self,nums):
if sum(nums)%2!=0:
return False
target = sum(nums)/2
dp = [0]*(target+1)
for num in nums:
for j in range(target,num-1,-1):
dp[j] = max(dp[j],dp[j-num]+num)
return dp[target] == target