子集和问题
问题定义
给定一个非负整型数值集合set,和一个值sum。如果集合的某个子集的和等于这个值,则返回true,否则返回false。
例如:集合为set = {12, 13, 4, 8, 5, 10}和sum = 9,那么SUM{4, 5} = 9,因此返回true。
算法分析
SubSetSum(set, n, sum) = SubSetSum(set, n - 1, sum) || SubSetSum(set, n - 1, sum - set[n - 1])
// 初始条件
SubSetSum(set, n, sum) = true, if sum = 0;
SubSetSum(set, n, sum) = false, if sum > 0 && n = 0;
算法实现
C++
// 递归版
bool SubSetSum(vector<int> data, int n, int sum) {
if(sum == 0)
return true;
if(sum != 0 && n == 0)
return false;
if(data[n-1] > sum)
return SubSetSum(data, n - 1, sum);
return SubSetSum(data, n - 1, sum) || SubSetSum(data, n - 1, sum - data[n - 1]);
}
问题拓展
分区和相等
问题1:将一个集合分成两个和相等的子集
给定一个非负整型集合,若能将其分为两个和相等的子集,则返回true,否则返回false。
解法分析
问题1
第一步,首先计算集合中元素的总和,如果和为奇数则返回false;如果和为偶数,进行第二步判断。
第二步,将上述算法中的sum,替换成sum/2即可。
bool SubSetSum(vector<int> data, int n, int sum) {
if(sum == 0)
return true;
if(sum != 0 && n == 0)
return fasle;
if(data[n - 1] > sum)
return SubSetSum(data, n - 1, sum);
return SubSetEqual(data, n - 1, sum) || SubSetEqual(data, n - 1, (sum - data[n - 1]));
}
bool SubSetEqual(vector<int> data) {
int sum = 0;
for(int i = 0; i < data.size(); i++) {
sum += data[i];
}
if((sum % 2) == 1)
return false;
else
return SubSetSum(data, data.size(), sum / 2);
}
分区和差值最小
问题2:将一个集合分成两个和的差值最小的子集
给定一个非负整型集合,将其分成两个和的差值最小的子集,并返回差值。
问题2
最后更新于