将一个数组分为两个子数组,使分别的和最接近
程序员文章站
2022-03-10 12:09:36
...
Problem
Split an array into two sub-arrays such that the absolute difference of two sums is minimal.
Solution 1: Enumeration
To generate sub-array 1, we either include i’th element or don’t include. In this way we can create a binary tree to DFS.
Solution 2: DP
0-1 背包问题。从前k个数中,取若干个,使其和为<= sum/2
的最大数。
即物品价值,重量都是数的值,背包容量为floor(sum/2)
,要使物品价值和最大。
void printAns(vector<int> &v, int sum){
int n = v.size(), m = sum / 2;
int dp[m+1] = {};
for(int i=1; i<=n; i++){
for(int j=m; j>=1; j--){
if(j>=v[i-1]) dp[j] = max(dp[j-v[i-1]]+v[i-1], dp[j]);
}
}
printf("%d %d\n", sum-dp[m], dp[m]);
return;
}
但只能适用于sum不大的情况,否则dp数组会超内存或超时。
Solution 3: 一个枚举的技巧
对于每个元素选或不选的枚举,可以用0-1串生成所有枚举情况。
有k个数,枚举所有选数情况(共2^k种),用1代表选,用0代表不选,那么所有情况是 000...000 ~ 111...111
,共k位
int maxcases = 1 << k; //2^k
for(int case=0; case<maxcases; case++){
//enumerate from 000...000 to 111...111
for(int pos=0; pos<k; pos++){
//check each bit position(0~k-1), if it is 1 then we include it into selection
if((case>>pos) & 1){
//include this one
}
}
}
以这样的枚举方式,找到和<=sum/2的最大数。
上一篇: 把一个数组分解成两个数组