题目链接:416. Partition Equal Subset Sum
题目大意:题目给出一个数组,分割成两个集合,判断这两个集合的和相等。
一.算法设计
这是一道经典的动态规划问题,判断子集合的和是否相等,由于集合的组成需要指数的构造时间,不符合题目要求的时间复杂度。这道算法题可以类比成背包问题。
既然要划分成两个集合的和都相等,那么我们先算出这个集合的总和,这个sum必须为偶数,才能划分成功
然后,这个sum的一半就是我们所要达到的目标。为什么说它像背包问题呢,因为这个sum的一半可以比作背包的容量w,我们想利用数组中的元素恰好填满这个w容量的背包,且其中的元素不能重复有且只有一个。
因此我们可以写出状态转移方程
dp[i] = dp[i] || dp[i-num]
其中dp[i]表达的是选取数组的元素,是否可以恰好填满容量i的背包。 若dp为1,则证明可以填充;dp为0则不能。
最后,我们只需要判断dp[target]是否为1即可,判断是否存在这样的划分。
注意点:
- 这里的遍历要求第一层遍历nums数组中的元素,第二层要从target值开始从后到前这样来遍历,避免数组越界的情况。
二.算法实现
class Solution {
public:
bool canPartition(vector<int>& nums) {
int sum = accumulate(nums.begin(), nums.end(), 0);
if(sum%2 != 0) return false;
int target = sum / 2;
vector<int> dp(target+1,0);
dp[0] = 1;
for(int num : nums){
for(int i = target; i >= num ; i--){
dp[i] = dp[i] || dp[i-num];
}
}
return dp[target];
}
};