前些時候面試碰到的題目:有兩個有序正整數陣列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...