交換兩個陣列的元素,使兩個陣列和的差最小

2021-05-26 20:23:17 字數 3155 閱讀 5378

前些時候面試碰到的題目:有兩個有序正整數陣列array1[n]、array2[m],通過交換兩陣列的元素,使兩個陣列的和最接近。

基本演算法思路:

每次從array1、array2選擇出一對能使交換後得array1和與array2和的差值變小的組合array1[i]、array2[j]作交換;直到對任意組合array1[i]、array2[j]作交換,array1和與array2和的差值都無法變得更小,演算法即結束。

網上查了下,基本有兩種演算法:

(1)       暴力演算法:採用雙重迴圈取逐一比較組合array1[i]、array2[j],只要交換能讓array1和與array2和的差值變小,即進行交換;直到演算法結束。

(2)       貪心演算法:採用雙重迴圈逐一比較取組合,找到交換後能讓array1和與array2和的差值變得最小的組合array1[i]、array2[j],才進行交換;直到演算法結束。

上面的貪心演算法中為尋找最優組合,採用雙重迴圈逐一比較,演算法時間複雜度最好也只有o(n*m) ( 若n=m即(n^2) )。自己琢磨了一段時間,同樣採用貪心演算法,發現尋找最優組合的演算法時間複雜度可以達o(n+m) ( 若n=m即(n) ),下面是相關分析:

假設sum(array1) > sum(array2):

當前陣列array1和陣列aarray2的和之差為:

a = sum(array1) - sum(array2)

對組合array1[i]、array2[j],交換後,array1與array2的和之差為:

a' = sum(array1) - array1 [i] + array2 [j] - (sum(array2) - array2 [j] + array1 [i])

= sum(array1) - sum(array2) - 2 (array1 [i] - array2 [j])

= a - 2 (array1 [i] - array2 [j])

設x = array1[i] - array2 [j]

最優組合即為使得x最接近a/2的一對array1[i]、array2[j]組合。

我給出的尋找最優組合的演算法思路:

首先,將i,j初始化為0,

若當前array1[i] - array2 [j]> a/2,即array2 [j]偏小;執行操作j++ 再進行比較;

若當前array1[i] - array2 [j]< a/2,即array2 [i]偏小;執行操作i++ 再進行比較;

直到i=n-1,j=m-1,演算法時間複雜度為o(n+m)。

舉例分析:

array1[length2]=    sum(array1)=  143

array2[length1]=    sum(array2)=  122

a = sum(array1) - sum(array2)=  21

a/2 = 10.5

需要找一組合array1[i]、array2[j],array1[i] - array2[j] 最接近10.5

第一次比較array1[ 0 ] - array2[ 0 ] = 4 < 10.5 然後i++

第二次比較array1[ 1 ] - array2[ 0 ] = 12 > 10.5然後j++

第三次比較array1[1 ] - array2[ 1 ] = 3 > 10.5然後j++

如下圖所示,總共最多進行了11次比較。

與雙重迴圈取逐一比較相比可以發現:雙重迴圈取逐一比較中很多的比較都是多餘的,因為對公升序陣列:

如果array1[ 0 ] - array2[ 0 ] = 4 < 10.5

必有array1[ 0 ] - array2[ 1 ] < array1[ 0 ] - array2[ 0 ] = 4 < 10.5

即與array1[ 0 ] 、array2[ 0 ]相比array1[ 0 ] - array2[ 1 ]絕不是更好的組合

所以接著只需對i++ 即array1[ 1 ] - array2[ 0 ] 與10.5 進行比較

如果array1[ 1 ] - array2[ 0 ] = 12 > 10.5

必有array1[ 2 ] - array2[ 0 ] > array1[ 1 ] - array2[ 0 ] = 12 > 10.5

即與array1[ 2 ] 、array2[ 0 ]相比array1[ 1 ] - array2[ 0 ]絕不是更好的組合

所以接著只需對j++ 即array1[ 1 ] - array2[ 1 ] 與10.5 進行比較

附帶c原始碼:

#include

#include

#define length1  8

#define length2  8

int endflag=0;

int ksort(int *array,int temp,int length,int j)            //用temp替換array[j],並將陣列排序

while(( karray[k] = temp;

return 0;

}int mini_tmp(int *min_i , int *min_j , int *min_temp, int now_temp, int i, int j) //如果當前組合比最優組合更好,則重置最優組合

return 0; 

}int kv_change(int *array1,int *sum1,int leng1,int *array2,int *sum2,int leng2,int flag)     //sum1if( (j==leng2-1)&&(i==leng1-1) )

else if( (j==leng2-1)&&(i temp1 )

else } 

}if( 1 )

else              // the end,no need to change anymore

}return 0;

}int main(void)

,array2[length2]=;

int i,j,k;

int temp = 0,temp1 = 0,temp2 = -1;

int sum1=0,sum2=0;

for(i=0;ikv_change(array1, &sum1, length1, array2, &sum2, length2, 1 );

}else

for(i=0;ireturn 0;

}

交換兩個陣列使兩個陣列和的差最小

有兩個陣列a,b,大小都為n,陣列元素的值任意整形數,無序 要求 通過交換a,b中的元素,使 陣列a元素的和 與 陣列b元素的和 之間的差最小。求解思路 當前陣列a和陣列b的和之差為 a sum a sum b a的第i個元素和b的第j個元素交換後,a和b的和之差為 a sum a a i b j ...

交換兩個陣列使兩個陣列和的差最小

有兩個陣列a,b,大小都為n,陣列元素的值任意整形數,無序 要求 通過交換a,b中的元素,使 陣列a元素的和 與 陣列b元素的和 之間的差最小。求解思路 當前陣列a和陣列b的和之差為 a sum a sum b a的第i個元素和b的第j個元素交換後,a和b的和之差為 a sum a a i b j ...

交換兩個陣列值使兩個陣列之差最小

有兩個序列a,b,大小都為n,序列元素的值任意整數,無序 要求 通過交換a,b 中的元素,使 序列a 元素的和 與 序列b 元素的和 之間的差最小。例如 var a 100,99,98,1,2,3 var b 1,2,3,4,5,40 假設序列a,b中元素的和為sum a和sum b。假設aa和bb...