交换ab两个数的值python_[微软]有两个序列a,b,大小都为n,序列元素的值任意整数,无序; 要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小_利用排列组合思路...

(原题出自微软公司面试题)问题如下:

有两个序列a,b,大小都为n,序列元素的值任意整数,无序;

要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小。

例如:

a=[100,99,98,1,2, 3]

b=[1, 2, 3, 4,5,40]

题目是看到QQ群友发的,网上也百度了下目前已经有好几种解法了。

写了半天有点晕,后面忽然想到中学时候数学里面的排列组合的方法。方法对于较短的list可行,长list组合情况太多,可能耗时太长或溢出。

1 from itertools importcombinations2

3 defget_combinations(arr):4 """获取所有组合结果,结果是生成器形式"""

5 arr.sort(reverse=True) #从大到小排序

6 for x in combinations(arr[1:], len(arr[1:]) // 2):7 yield arr[0:1] + list(x) #捆绑法,捆绑一个最大值

8

9 defget_abs_mins(avs,arr):10 """返回各个list平均值与所有数平均值差的绝对值迭代对象"""

11 for x inarr:12 abs_min = abs(sum(x)/len(x)-avs)13 yieldabs_min14 if abs_min == 0: #绝对值为0时,停止比较

15 break

16

17 defrun(arr1,arr2):18 arr = arr1 + arr2 #合并list

19 avs = sum(arr) / len(arr) #求所有数的平均值

20 abs_min = min(get_abs_mins(avs, get_combinations(arr))) #求组合后的平均值与所有值平均值差的最小值

21

22 i = 1

23 for x inget_combinations(arr):24 if abs(sum(x) / len(x) - avs) ==abs_min:25 x_ =arr[:]26 for e inx:27 x_.remove(e) #删除x中的元素

28 #i为比较次数,x是第一个list,x_是第2个list

29 print("循环次数:%s\nlist1:%s\nlist2:%s\nlist1求和:%s\nlist2求和:%s"%(i,list(x),x_,sum(x),sum(x_)))30 returnx,x_31 break

32 i += 1

33

34 if __name__ == ‘__main__‘:35 a = [100, 99, 98, 1, 2, 3]36 b = [1, 2, 3, 4, 5, 40]37 try:38 x,x_ = run(arr1=a,arr2=b)39 #print(x)

40 #print(x_)

41 except:42 pass

运行结果:

循环次数:337

list1:[100, 40, 5, 4, 3, 3]

list2:[99, 98, 2, 2, 1, 1]

list1求和:155

list2求和:203

改变a、b的值

a = [100, 99, 98, 1, 2, 3] + [(i+2)*(i+7) for i in range(6)]

b = [1, 2, 3, 4, 5, 40] + [(i+2)**2 for i in range(6)]

运行结果:

循环次数:201546

list1:[100, 99, 98, 66, 5, 4, 4, 3, 3, 2, 1, 1]

list2:[84, 50, 49, 40, 36, 36, 25, 24, 16, 14, 9, 2]

list1求和:386

list2求和:385

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值