LeetCode:89.分割等和子集
目录
1.分割等和子集
1.分割等和子集
对于这道题,我们可以先计算数组的总和,如果总和为奇数的话,就不需要后面的判断了,奇数和肯定无法分割等和子集
和sum为偶数后,我们可以将其看作一个背包问题,我们需要从数组中找到和为sum/2的数组,所以我们就将其转化为背包问题
设dp[i][j]表示能否从前i个数字中找到和为j的数组,分为以下情况:
- 选择i这个数,dp[i][j] = dp[i - 1][j - nums[i]]
- 不选择i这个数,dp[i][j] = dp[i - 1][j]
我们取这两种结果的或运算,只要满足一种即可
class Solution {
public:bool canPartition(vector<int>& nums) {int n = nums.size(), sum = 0;for(auto x : nums) sum += x;if(sum % 2 == 1) return false;int aim = sum / 2;vector<vector<bool>> dp(n + 1, vector<bool>(aim + 1));for(int i = 0; i <= n; i++) dp[i][0] = true;for(int i = 1; i <= n; i++)for(int j = 0; j <= aim; j++){dp[i][j] = dp[i - 1][j];if(j >= nums[i - 1])dp[i][j] = dp[i][j] || dp[i - 1][j - nums[i - 1]];}return dp[n][aim];}
};
空间优化后
class Solution {
public:bool canPartition(vector<int>& nums) {int n = nums.size(), sum = 0;for(auto x : nums) sum += x;if(sum % 2 == 1) return false;int aim = sum / 2;vector<bool> dp(aim + 1);dp[0] = true;for(int i = 1; i <= n; i++)for(int j = aim; j >= nums[i - 1]; j--)dp[j] = dp[j] || dp[j - nums[i - 1]];return dp[aim];}
};