@bergus
2015-12-05T14:49:03.000000Z
字数 1499
阅读 2677
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为止。
#思路是有等长的两个列表a,b;a,b组成一个大列表_list然后从大到小排序;求出列表a,b各自的和s1,s2,然后比较;如果s1,s2的差值大于_list中的最大值,那么列表和小的就加上这个最大值,而列表和大的就加上_list的最小值;如果s1,s2的差值小于_list中的最大值,那么列表和小的就加上这个最大值,而列表和大的就加上_list的次大值;
a = [1,2,3,4,5,6,7];
b = [8,9,11,1,33,4,5,6];
source = a + b
source.sort(reverse=True)
print source
while True:
s1,s2 = sum(m1),sum(m2)
if s1 > s2:
if s1 - s2 >= source[0]:
m2.append(source.pop(0) if len(source) >=1 else 0)
m1.append(source.pop() if len(source) >=1 else 0)
else:
m2.append(source.pop(0) if len(source) >=1 else 0)
m1.append(source.pop(0) if len(source) >=1 else 0)
else:
if s2 - s1 >= source[0]:
m1.append(source.pop(0) if len(source) >=1 else 0)
m2.append(source.pop() if len(source) >=1 else 0)
else:
m1.append(source.pop(0) if len(source) >=1 else 0)
m2.append(source.pop(0) if len(source) >=1 else 0)
print m1,m2
if len(source) == 0:
break
print sum(m1)-sum(m2)