[关闭]
@bergus 2015-12-05T14:49:03.000000Z 字数 1499 阅读 2677

有两个序列a,b,大小都为n,序列元素的值任意整数,无序;要求:通过交换a,b 中的元素,使[序列a 元素的和]与[序列b 元素的和]之间的差最小。

python 算法


有两个序列a,b,大小都为n,序列元素的值任意整数,无序;要求:通过交换a,b 中的元素,使[序列a 元素的和]与[序列b 元素的和]之间的差最小。

例如:
var a = [100,99,98,1,2, 3];
var b = [1, 2, 3, 4,5,40];

最后的结果为:
var a = [1,99,98,1,2,2];
var b = [100, 3,3,4,5,40];

思路一:
首先先计算a,b中元素和之间的差绝对值ABDis,然后逐一的把a中的元素和b中的任一元素作比较,如果它们交换后的差值绝对值ABTempDis小于原来的值ABDis,那么就把a,b交换,并重新计算a和b的绝对值,这种动作反复的进行,直到a中任一的元素都不能和b中的任一元素交换为止。(其实是穷举法)

思路二:
当前数组a和数组b的和之差为A = sum(a) - sum(b),a的第i个元素和b的第j个元素交换后,a和b的和之差为
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])
设x = a[i] - b[j],那么
A' = |A - 2x|,当然A' 越小也好,所以当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. #思路是有等长的两个列表a,b;a,b组成一个大列表_list然后从大到小排序;求出列表a,b各自的和s1,s2,然后比较;如果s1,s2的差值大于_list中的最大值,那么列表和小的就加上这个最大值,而列表和大的就加上_list的最小值;如果s1,s2的差值小于_list中的最大值,那么列表和小的就加上这个最大值,而列表和大的就加上_list的次大值;
  2. a = [1,2,3,4,5,6,7];
  3. b = [8,9,11,1,33,4,5,6];
  4. source = a + b
  5. source.sort(reverse=True)
  6. print source
  7. while True:
  8. s1,s2 = sum(m1),sum(m2)
  9. if s1 > s2:
  10. if s1 - s2 >= source[0]:
  11. m2.append(source.pop(0) if len(source) >=1 else 0)
  12. m1.append(source.pop() if len(source) >=1 else 0)
  13. else:
  14. m2.append(source.pop(0) if len(source) >=1 else 0)
  15. m1.append(source.pop(0) if len(source) >=1 else 0)
  16. else:
  17. if s2 - s1 >= source[0]:
  18. m1.append(source.pop(0) if len(source) >=1 else 0)
  19. m2.append(source.pop() if len(source) >=1 else 0)
  20. else:
  21. m1.append(source.pop(0) if len(source) >=1 else 0)
  22. m2.append(source.pop(0) if len(source) >=1 else 0)
  23. print m1,m2
  24. if len(source) == 0:
  25. break
  26. print sum(m1)-sum(m2)
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注