416. 分割等和子集
给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
示例 1:
输入: [1, 5, 11, 5]
输出: true
解释: 数组可以分割成 [1, 5, 5] 和 [11].
示例 2:
输入: [1, 2, 3, 5]
输出: false
解释: 数组不能分割成两个元素和相等的子集.
提示:
每个数组中的元素不会超过 100
数组的大小不会超过 200
解题思路(动态规划 0-1背包)
题目要求分割两个子集的元素和相等,那么只要找到集合里能够出现sum / 2
的子集总和,就可以保证分割成两个相同元素和子集。因此可以转化为0-1背包问题,容量为sum / 2
- 状态表示与转移方程:
dp[j]
:容量为j
的背包,物品价值可以为dp[j]
dp[j] = max(dp[j], dp[j - nums[i]] + nums[i])
C++版本 |
class Solution {
public:
bool canPartition(vector<int>& nums) {
int n = nums.size(),S = accumulate(nums.begin(),nums.end(),0);
if(S & 0x1) return false;
int cur = S >> 1;
vector<int> dp(cur + 1,0);
dp[0] = 0;
for(int x:nums){
for(int j = cur; j >= x; j--){
dp[j] = max(dp[j],dp[j - x] + x);
}
}
return dp[cur] == cur;
}
};
Python版本 |
class Solution:
def canPartition(self, nums: List[int]) -> bool:
S = sum(nums)
if S % 2 == 1:
return False
cur = S // 2
dp = [0] * (cur + 1)
for x in nums:
for j in range(cur,x - 1,-1):
dp[j] = max(dp[j],dp[j - x] + x)
return True if dp[cur] == cur else False