1 题目
给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
示例 1:
输入:nums = [1,5,11,5]
输出:true
解释:数组可以分割成 [1, 5, 5] 和 [11] 。
示例 2:
输入:nums = [1,2,3,5]
输出:false
解释:数组不能分割成两个元素和相等的子集。
2 解析
动态规划方法:
和 279. 完全平方数类似的思想,用枚举的累计和方法
整个集合总和的一半为maxn,
我们可以枚举1到maxn的数,即maxn大的数组,表示为dp
状态:dp[i]表示加上i后子集的累计值
我们要计算子集和是否等于maxn,这需要去计算 i − n u m s [ i ] i-nums[i] i−nums[i]位置的累计和 。此时我们发现该子问题和原问题类似,只是规模变小了。这符合了动态规划的要求,于是我们可以写出状态转移方程。
$$dp[i]=\max_{j=0}^{maxn}(f[i],f[i-nums[i]]+nums[i])$$
初始化dp[i]=0
最后判断dp[maxn]是否等于maxn,如果等于,说明,子集和等于maxn,返回True
3 python实现
class Solution:
def canPartition(self, nums: List[int]) -> bool:
all = sum(nums)
if(all % 2 != 0): return False
maxn = int(all / 2)
dp = [0]*(maxn + 1)
for i in range(len(nums)):
for j in range(maxn,nums[i]-1,-1):
# 更新每个位置的值
dp[j] = max(dp[j], dp[j - nums[i]] + nums[i])
return dp[maxn] == maxn