描述
给定一个int类数据集合,你需要判断这两个数据集合能否分成两个相等的部分,也就是说一部分等于总和的一般
我想了一个算法,枚举,O(2^N),(* ̄ω ̄)
我的解法
1 | class Solution { |
这个是我写的一个递归的版本,好像没有什么效果。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33public:
bool canPartition(vector<int>& nums) {
int sumval = accumulate(nums.begin(), nums.end(), 0);
if (sumval % 2 == 1) { return false; }
int midval = sumval / 2;
int nNums = nums.size();
for (auto num : nums) {
if (num > midval) {
return false;
}
}
if(findn(nNums-1,midval,nums)==ture){return true;}
return false;
}
bool findn(int iNum, int midval, vector<int>& nums) {
if (midval == 0) {
return true;
}
if (midval < 0) {
return false;
}
if (iNum == 0 && midval == nums[0]) {
return true;
}
if (iNum == 0 && midval != nums[0]) {
return false;
}
return findn(iNum - 1, midval - nums[iNum], nums) || findn(iNum - 1, midval, nums);
}
};
更好的解法
参考链接
基于贪心的dp算法,强大。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25class Solution {
public:
bool canPartition(vector<int>& nums) {
int sum = accumulate(nums.begin(), nums.end(), 0);
if (sum & 1) { return false; }
int half = sum / 2;
//sort it from big to small then you can use dp
//it is quickly,because it's greedy
sort(nums.begin(), nums.end(), greater<int>());
return canPartitionRecrusion(nums, half, 0);
}
bool canPartitionRecrusion(vector<int>& nums,int half,int index) {
for (int i = index; i < nums.size(); i++) {
int h = half - nums[i];
if (h == 0) { return true; }
if (h <0) { return false; }
if (canPartitionRecrusion(nums, h, i + 1) == true) { return true; };
}
return false;
}
};
另一种解法
代码很精炼,有点难理解,下标即总和,厉害。
实际上利用了一个数组模拟了所有的加法总和情况,太精巧了。Ψ( ̄∀ ̄)Ψ1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Solution {
public:
bool canPartition(vector<int>& nums) {
int sum = std::accumulate(nums.begin(), nums.end(), 0);
if (sum%2!=0) return false;
vector<int> dp(sum+1, 0);
dp[0] = 1;
for (const int num: nums){
for (int i= sum; i>=0; --i){
if (dp[i]) dp[i+num]= true;
}
if (dp[sum/2]) return true;
}return false;
}
};
参考资料
原题链接