《程式設計之美》讀書筆記10: 2.18 陣列分割
如果直接遍歷,則至少要遍歷 cr(n-1,2*n)次(cr(m,n)為從n個數中取m個數的組合數),為了減少遍歷次數,可以先對陣列排序。再將所有可能的組合大致分成幾組,每個組的陣列和也是公升序的,通過不斷的分組、查詢,確定上下邊界條件,最終找到所求子陣列。
如果陣列各個元素均不相同,可以採用下面的演算法:
先將陣列排序,並計算出各元素的總和的一半s(=sum/2.0),(對陣列的劃分時,可以先選中a0,再取n-1個數)。
假設ti=sum(a0+ai+an+2+an+3…+a2n-1) (0則陣列也是公升序。如果tn+1
<=s則tn+1即為所求,如果存在ti=s,則ti即為所求。否則,可以通過二分法找到唯一的i、j使得ti
j,(選中a0和aj),記錄ti,假設ri=sum(a0+aj+ai+an+3+an+4…+a2n-1) (j,則tj=rn+2,比較ti、rj+1、rn+2,再對ri進行類似ti的分析,找出下乙個數。通過不斷的分組和查詢和判斷,最終可以找到所求的n個數。
例如:長度為8的陣列:共有35種組合,對每種組合的子陣列和,可以劃分到幾個區間:(下面的0123表示取a0+a1+a2+a3)
較小值較大值
0123
——0167 (共15個)
0234
——0267 (共10個)
0345
——0367 (共6個)
0456
——0467 (共3個)
0567
——0567 (共1個)
(各個較大值不必計算,它們間必然只有乙個數不同(並且這個不同的數在公升序數列中的位置是連續的),查詢s在哪兩個較大值之間,可以用s減去相同的數的和,得到的差去指定的範圍(不同的那個數的位置範圍)進行二分查詢。)
由於陣列是公升序,陣列元素各不相同,右邊的「較大值」都是公升序排列且不會重複。利用陣列和的一半s進行查詢,如果s在0267和0367之間。只要記錄0267,並在適當時候判斷該記錄是否是所求的,展開0345——0367的6個數,
0345
—— 0347(共3個)
0356
—— 0357(共2個)
0367
—— 0367(共1個)
再重複上述操作。
《程式設計之美》讀書筆記
程式設計之美 讀書筆記 一 中國象棋將帥問題 程式設計之美 讀書筆記 二 求二進位制數中1的個數 擴充套件問題 程式設計之美 讀書筆記 三 一摞烙餅的排序問題 程式設計之美 讀書筆記 四 買書折扣問題的貪心解法 程式設計之美 讀書筆記 五 飲料 問題 程式設計之美 讀書筆記 六 連連看遊戲設計 程式...
《程式設計之美》讀書筆記集錦
程式設計之美 讀書筆記 一 中國象棋將帥問題 程式設計之美 讀書筆記 二 求二進位制數中1的個數 擴充套件問題 程式設計之美 讀書筆記 三 一摞烙餅的排序問題 程式設計之美 讀書筆記 四 買書折扣問題的貪心解法 程式設計之美 讀書筆記 五 飲料 問題 程式設計之美 讀書筆記 六 連連看遊戲設計 程式...
《程式設計之美》讀書筆記集錦
程式設計之美 讀書筆記 一 中國象棋將帥問題 程式設計之美 讀書筆記 二 求二進位制數中1的個數 擴充套件問題 程式設計之美 讀書筆記 三 一摞烙餅的排序問題 程式設計之美 讀書筆記 四 買書折扣問題的貪心解法 程式設計之美 讀書筆記 五 飲料 問題 程式設計之美 讀書筆記 六 連連看遊戲設計 程式...