有兩個序列 a,b,大小都爲 n,序列元素的值任意整數,無序;算法
經過交換 a,b 中的元素,使[序列 a 元素的和]與[序列 b 元素的和]之間的差最小。spa
例如:
var a = [100,99,98,1,2, 3];
var b = [1, 2, 3, 4,5,40];3d
最後的結果爲:
var a = [1,99,98,1,2,2];code
var b = [100, 3,3,4,5,40];orm
最簡單的方法應該就是暴力窮舉it
這裏闡述在網上看到的另外一種方法:io
對於序列a和b,令A = sum(a) - sum(b)編譯
分別用i,j遍歷a,b序列,若a[i]和b[j]交換class
則:A' = sum(a) - a[i] + b[j] - (sum(b) - b[j] + a[i])
= sum(a) - sum(b) - 2 (a[i] - b[j])
= A - 2 (a[i] - b[j])遍歷
即就是:(a[i] - b[j])在(0,A)之間而且最接近A/2則序列a,b的差值最小
所以獲得算法:
在a和b中尋找使得x在(0,A)之間而且最接近A/2的i和j,交換相應的i和j元素,從新計算A後,重複前面的步驟直至找不到(0,A)之間的x爲止。
(GCC編譯經過)
#include "stdio.h" #include "stdlib.h" void balanceArray(int a[],int b[],int n); int sumArray(int a[],int n); int main(void) { int i; int a[5]={0,1,2,3,4},b[5]={5,6,7,8,9}; balanceArray(a,b,5); for(i=0;i<5;i++) printf("%3d",a[i]); printf("\n"); for(i=0;i<5;i++) printf("%3d",b[i]); printf("\n"); return 0; } void balanceArray(int a[],int b[],int n) { int *p,*q; int i,j,itemDValue,sumDValue,tmp,flag=1; if(sumArray(a,n) < sumArray(b,n)) { p = b; q = a; } while(flag) { flag=!flag; for(i=0;i<n;i++) { for(j=0;j<n;j++) { itemDValue = p[i]-q[j]; sumDValue = sumArray(p,n) - sumArray(q,n); if((itemDValue < sumDValue)&&(itemDValue > 0)) { flag=!flag; tmp = p[i]; p[i] = q[j]; q[j] = tmp; } } } } } int sumArray(int a[],int n) { int i,count=0; for(i=0;i<n;i++) count += a[i]; return count; }