程式設計之美 2 18 陣列分割

2022-05-18 10:34:11 字數 2603 閱讀 9431

題目:

有乙個無序、元素個數為2n的正整數陣列,要求:如何能吧這個陣列分割為元素個數為n的兩個陣列,並使兩個子陣列的和最近?

例如有如下陣列如圖:

思路:程式設計之美的書上解法一中說我們直觀的思路是對所有元素排序

s:a0 < a1 < a2 ... < a2n-1

然後分為

s1 = [a1, a3, ...,a2n-1]

s2 = [a0, a2, ...,a2n-2]

我的思路的前面也是這樣的,不過後面有加了一步:

對s陣列 分為n組[a0 a1][a2 a3][a4 a5]...[a2n-2 a2n-1]

每一組的數字都是相鄰的 然後我們對這個s按照組來排序, 把每一組中數字差值大的組放在前面, 差值小的放在後面

然後用diff記錄s1-s2的變化,如果diff < 0 則說明前面的和s1偏小,那麼我們就把當前組的s1和s2的數字交換 減小diff

如果diff大於等於0,由於s1原本的數字就是較小的,不用交換,直接更新diff就可以了。

而且:由於我們每次都是填充差距最大的對,兩個組的和之差只會越來越小。

注:雖然沒有證明其正確性,但是我也舉不出反例來。對於有負數的情況**依然運轉的很好。 時間複雜度也只有o(nlogn),空間複雜度也只有o(n),因為除了排序,我完全是在原地操作的。 比書上解法二和解法三的效率要高得多。

question:誰能幫我舉出這種思路無法正確處理的反例嗎?

答:突然發現,下面的例子裡面就有反例

拿50  100

40  30

49  48

45  44

22  21

sum:206 243

其實把左右的22 和 48 換一下 差值就變小了。唉,果然簡便演算法不對,還是老老實實看書吧。

**如下:

//

start time 10:45

//end time 11:30

#include

#include

int cmp1(const

void * p1, const

void *p2)

int cmp2(const

void * p1, const

void *p2)

void getclosedtwoarray(int * a, int

alen)

//從小到大排序

qsort(a, alen, sizeof(a[0

]), cmp1);

//a中兩個相鄰元素為一組 按照每組元素的差值的絕對值 從大到小排序

qsort(a, alen >> 1, 2 * sizeof(a[0

]), cmp2);

int diff = 0; //

偶數字陣列 減 奇數字陣列的差值

把書上的正確答案記錄一下:

我偷懶,直接copy人家已經寫好了的

方法二,動態規劃,原題是要求求兩個陣列的和最近接,這等價於要求其中較小的和最接近與2n個正整數的和(設為sum)的一半。因此,弱化題目,求這個最近接一半的且小於等於sum/2數值,定義heap[i],i<=n表示任意i個數能夠構成的數值集合。初始化:heap[0]= 0。更新**:

for(int i=1; i<2*n; i++) ; j>0; j--) // 更新引入a[i]後可能的元素個數的情況

for each v in heap[j-1] // 對於引入a[i]的情況

insert(heap[j], a[i]+v);

}

關於insert次數,至多為2^(n-1)。

方法三,複雜度主要是由於堆很大,原因是我們記錄的是各種可能組合出的數值。如果sum值不高,可以定義bool flag[i][j],i=0,1,...,2*n,j=0,1,...,sum/2,表示是否存在i個數,其和為j。初始化,flag[0][0] = true。

for(int k=1; k<2*n; k++) ; i>0; i--)     

}}

max,其中,j=0,1,...,2*n,flag[n][j]=true,這即為所求。這樣複雜度為o(n*n*sum)級別的,尤其是當sum相對不大的時候,複雜度會大大降低。

《程式設計之美》 2 18 陣列分割

題目概述 有乙個沒有排序,元素個數為2n的正整數陣列。要求把它分割為元素個數為n的兩個陣列,並使兩個子陣列的和最接近。假設陣列a 1.2n 所有元素的和是sum。模仿動態規劃解0 1揹包問題的策略,令s k,i 表示前k個元素中任意i個元素的和的集合。顯然 s k,1 s k,k s k,i s k...

程式設計之美 2 18 陣列分割

本人第一次寫部落格,如有不對,請多加指正。解法一的思路很明顯是錯的。貪心演算法很多情況下求不出最佳解答,因為可能兩個陣列間需要同時交換兩個或者兩個以上的數,才能實現差值最小。如 解法二的思路將也就是乙個組合的問題在2n個陣列中找出n個數,使得n個數之和最接近於sum 2,這裡取小於等於sum 2的情...

《程式設計之美》 2 18 陣列分割

題目概述 有乙個沒有排序,元素個數為2n的正整數陣列。要求把它分割為元素個數為n的兩個陣列,並使兩個子陣列的和最接近。假設陣列a 1.2n 所有元素的和是sum。模仿動態規劃解0 1揹包問題的策略,令s k,i 表示前k個元素中任意i個元素的和的集合。顯然 s k,1 s k,k s k,i s k...