交换a,b中的元素,使|sum[a]-sum[b]|最小

转自:http://blog.csdn.net/beiyeqingteng/article/details/6958320

有两个序列a,b,大小都为n,序列元素的值任意整数,无序; 
要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小。 
例如:   
var a=[100,99,98,1,2, 3]; 
var b=[1, 2, 3, 4,5,40];(微软100题第32题)。 
假设当前数组和的差为A:A = sum[a] - sum[b]
交换两个元素a[i],b[i],则差为
A' = sum[a] -a[i]+b[i] - (sum[b]-b[i]+a[i])
    =  sum[a]-sum[b]-2(a[i]-b[i])
    = A-2x   (设x = a[i]-b[i],) 
假设A > 0, 当x 在 (0,A)之间时,做这样的交换才能使得交换后的a和b的和之差变小,x越接近A/2效果越好, 如果找不到在(0,A)之间的x,则当前的a和b就是答案。 所以算法大概如下:
在a和b中寻找使得x在(0,A)之间并且最接近A/2的i和j,交换相应的i和j元素,重新计算A后,重复前面的步骤直至找不到(0,A)之间的x为止。

代码如下:

 1 #!/usr/bin/python
 2 
 3 #a = [100, 99, 98, 1, 2, 3]
 4 #b = [1, 2, 3, 4, 5, 40]
 5 
 6 a = [100, 1, 2, 3]
 7 b = [1, 2, 3, 96]
 8 
 9 sum1 = sum(a)
10 sum2 = sum(b)
11 
12 if sum1 > sum2:
13     big, small = a, b
14 else:
15     big, small = b, a
16 
17 shift = True
18 while shift:
19     diff = abs(sum(big)-sum(small))
20     maxdiff = diff     #used to choose the best tempdiff
21     shift = False
22     for iv in big:
23         for jv in small:
24             tempdiff = abs(diff - 2*(iv-jv))
25             if tempdiff < diff and tempdiff < maxdiff:
26                 shift = True
27                 maxdiff = tempdiff
28                 pa = big.index(iv)
29                 pb = small.index(jv)
30     if shift:
31         big[pa], small[pb] = small[pb], big[pa]
32 
33 print a
34 print b

 

posted @ 2012-10-17 16:43  dandingyy  阅读(446)  评论(0编辑  收藏  举报