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

Posted python菜鸟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[微软]有两个序列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

以上是关于[微软]有两个序列a,b,大小都为n,序列元素的值任意整数,无序; 要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小_利用排列组合思路解决_python版的主要内容,如果未能解决你的问题,请参考以下文章

练习五十一:序列交换

给定两个长度都为N的序列A,B,在A和B中各取一个数相加可以得到N^2个和,从小到大输出这N^2个和中最小的N个

交换两个序列的元素,使得元素和的差异变得最小。

bzoj2962序列操作 线段树

Problem B: 序列合并

BZOJ_2962_序列操作_线段树