给你一个 只包含正整数 的 非空 数组 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]位置的累计和 。此时我们发现该子问题和原问题类似,只是规模变小了。这符合了动态规划的要求,于是我们可以写出状态转移方程。
d p [ i ] = max j = 0 m a x n ( f [ i ] , f [ i − n u m s [ i ] ] + n u m s [ i ] ) dp[i]=\max_{j=0}^{maxn}(f[i],f[i-nums[i]]+nums[i]) dp[i]=j=0maxmaxn(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