1. 程式人生 > >有兩個序列a,b,大小都為n,序列元素的值任意整數,無序;要求:通過交換a,b中的元素,使[序列a元素的和

有兩個序列a,b,大小都為n,序列元素的值任意整數,無序;要求:通過交換a,b中的元素,使[序列a元素的和

原題:有一序列a,大小為n,分為2部分,序列元素的值任意整形數,無序;

要求:通過交換a,b中的元素,使[序列a元素的和]與[序列b元素的和]之間的差最小,用python寫。

#coding=utf-8
# 1.將兩序列合併為一個序列,並排序,為序列Source
# 2.拿出最大元素Big,次大的元素Small
# 3.在餘下的序列S[:-2]進行平分,得到序列max,min
# 4.將Small加到max序列,將Big加大min序列,重新計算新序列和,和大的為max,小的為min。
# Python程式碼
def mean(sorted_list):
    if not sorted_list:
        return(([],[]))
    big=sorted_list[-1]
    small=sorted_list[-2]
    big_list,small_list=mean(sorted_list[:-2])
    big_list.append(small)
    small_list.append(big)
    big_list_sum=sum(big_list)
    small_list_sum=sum(small_list)
    if big_list_sum>small_list_sum:
        return((big_list,small_list))
    else:
        return((small_list,big_list))
li=[5,5,9,9,1]
l =[4,7,7,8,5]
l.extend(li)
l.sort()
l1,l2=mean(l)
print l1,l2
print ('Distance:%s'%abs(sum(l1)-sum(l2)))
print ('-*'*40)
# 輸出結果
# [4, 5, 5, 7, 9] [1, 5, 7, 8, 9]
# Distance:0


解題思路一:

1.列表合併排序,設兩個空列表
2.最大值新增第一個列表
3.比較兩個列表差,迴圈放入最小列表中

程式碼如下(Python2.7.5):

list1=[1,21,3,14]
list2=[8,4,5,7]
li=[]
lis3 = []
lis4 = []

for i in list1:
    li.append(i)
for i in list2:
    li.append(i)

li.sort()
sum1=sum(lis3)
sum2=sum(lis4)
i = len(li) - 1

while i >= 0 :
    if sum1>=sum2:
        lis4.append(li[i])
        sum2=sum(lis4)
    else:
        lis3.append(li[i])
        sum1=sum(lis3)
    i-=1
if sum1>=sum2:
    cha = sum1-sum2
else:
    cha = sum2-sum1

print lis3
print lis4
print sum1
print sum2
print cha

解題思路二:

假如最小數是負數,這樣題目就很簡單,程式碼如下:

li1=[1,21,3,14]
li2=[8,4,5,7]

sourcelist=[]

for i in li1:

        sourcelist.append(i)
for j in li2:
        sourcelist.append(j)
sourcelist.sort()

size=len(sourcelist)/2

sourcelist.sort()

print sum(sourcelist[:size])-sum(sourcelist[size:])

假如最小值為正數,當前陣列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'| = |A| - |A-2x|
    
    |A'|= |A-2x|
    假設A > 0,
    當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為止。

def change(llist, rlist):
    r = lenth - 1
    tflag = 1
    global flag
    global cha
    while r >= 0 and tflag:
        for l in range(lenth):
            if ((rlist[r] - llist[l]) * 2 <= cha and rlist[r] > llist[l]):
                rlist[r], llist[l] = llist[l], rlist[r]
                rlist.sort()
                llist.sort()
                cha = sum(rlist) - sum(llist)
                tflag = 0
                break
        else:
            r -= 1

    if (r < 0):
        flag = 0
    return (llist, rlist)


if (__name__ == '__main__'):
    li1=[1,21,3,14]
    li2=[8,4,5,7]
    sourcelist=[]
    for i in li1:
        sourcelist.append(i)
    for j in li2:
        sourcelist.append(j)
    sourcelist.sort()
    lenth = len(sourcelist) / 2
    llist = sourcelist[:lenth]
    rlist = sourcelist[lenth:]
    cha = sum(rlist) - sum(llist)
    flag = 1
    while flag:
        (llist, rlist) = change(llist, rlist)
    print llist, sum(llist)
    print rlist, sum(rlist)
    print cha