416. 分割等和子集
问题
给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
示例 1:
输入:nums = [1,5,11,5]
输出:true
解释:数组可以分割成 [1, 5, 5] 和 [11] 。
示例 2:
输入:nums = [1,2,3,5]
输出:false
解释:数组不能分割成两个元素和相等的子集。
分析
经过尝试,这题最好递推,不然记忆递归几乎都会超时。
法一、暴力递归,超时,测试用例39/147
class Solution {
public:
int target = 0;
int n_n = 0;
vector<int> q;
bool res = false;
void dfs(int x, int cur_sum) {
if (cur_sum == target) {
res = true;
return ;
}
if (cur_sum > target || x >= n_n) {return ;}
dfs(x+1, cur_sum); // 不选
dfs(x+1, cur_sum+q[x]); // 选
}
bool canPartition(vector<int>& nums) {
this->n_n = nums.size();
this->q = nums;
for (int i = 0; i < n_n; i++) {
target += nums[i];
}
if (target % 2) {return false;}
target /= 2;
dfs(0, 0);
return res;
}
};
法二、基于unordered_map的记忆递归,仍然超时,141/147
class Solution {
public:
int target = 0;
int n_n = 0;
vector<int> q;
unordered_map<int, unordered_map<int, bool>> mem;
bool dfs(int x, int cur_sum) {
if (mem.count(x) && mem[x].count(cur_sum)) {
return mem[x][cur_sum];
}
if (cur_sum == target) {
mem[x][cur_sum] = true; return true;
}
if (cur_sum > target || x >= n_n) {
mem[x][cur_sum] = false; return false;
}
bool t1, t2;
t1 = dfs(x+1, cur_sum); // 不选
t2 = dfs(x+1, cur_sum+q[x]); // 选
bool ans = t1 || t2;
mem[x][cur_sum] = ans;
return ans;
}
bool canPartition(vector<int>& nums) {
this->n_n = nums.size();
this->q = nums;
for (int i = 0; i < n_n; i++) {
target += nums[i];
}
if (target % 2) {return false;}
target /= 2;
bool res = dfs(0, 0);
return res;
}
};
法三、基于vector<vector<>>的记忆递归
但是类似于计数排序,如果target过大,vector将会爆内存。
class Solution {
public:
int target = 0;
int n = 0;
vector<int> nums;
vector<vector<int>> memo; // -1:未访问,0:不可行,1:可行
bool dfs(int i, int cur_sum) {
if (cur_sum == target) return true;
if (cur_sum > target || i >= n) return false;
if (memo[i][cur_sum] != -1) return memo[i][cur_sum];
bool res = dfs(i + 1, cur_sum) || dfs(i + 1, cur_sum + nums[i]);
memo[i][cur_sum] = res;
return res;
}
bool canPartition(vector<int>& nums) {
this->nums = nums;
this->n = nums.size();
int total = 0;
for (int num : nums) total += num;
if (total % 2 != 0) return false;
target = total / 2;
memo = vector<vector<int>>(n, vector<int>(target + 1, -1));
return dfs(0, 0);
}
};

浙公网安备 33010602011771号