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

(原题出自微软公司面试题)问题如下:
有两个序列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 import combinations
 2 
 3 def get_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 def get_abs_mins(avs,arr):
10     """返回各个list平均值与所有数平均值差的绝对值迭代对象"""
11     for x in arr:
12         abs_min = abs(sum(x)/len(x)-avs)
13         yield abs_min
14         if abs_min == 0: #绝对值为0时,停止比较
15             break
16 
17 def run(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 in get_combinations(arr):
24         if abs(sum(x) / len(x) - avs) == abs_min:
25             x_ = arr[:]
26             for e in x:
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             return x,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

转载于:https://www.cnblogs.com/pyspider/p/7355622.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值