序列的劃分

2021-07-02 04:18:54 字數 1794 閱讀 3922

序列的劃分問題描述如下:

輸入:序列a[p...r]

輸出:下標q(p≤q≤r),原序列a[p...r]的乙個重排:使得a[p...q]中的元素值不超過a[q](=原a[r]的值),a[q+1...r]中的元素值均大於a[q]。

解決此問題的演算法對序列a[p...r]進行原地重組。演算法選擇元素x=a[r]作為主元素,以它為分界點對序列a[p...r]進行劃分,目標是將其分成前後兩段a[p...q]和a[q+1...r],使得a[p...q]中的元素值不超過x,而a[q+1...r]中的元素值大於x。

演算法維護兩個下標值i和j,初始值分別為p-1和p。讓j在[p...r]中掃瞄,若a[j]≤a[r],則將a[j]與a[i+1]交換,然後i增加1。這樣,在此過程中,a[p...i]中的元素均不超過a[r],而a[i+1...j]中的元素大於a[r]。隨著j的增加,a[p...i]和a[i+1...j]也隨之增長,最後j達到r-1,並將a[r+1]和a[r]交換,返回i+1即為所求的q。

例如對下圖中所示的序列進行的操作:

圖:對乙個樣本序列的劃分操作。淺藍色陣列元素都在第一部分a[p...i]中,其值都不大於x。深藍色陣列元素都在第二部分a[i+1,j]中,其值都大於x。無陰影元素是尚未進入上述兩個部分的元素,黑色元素是基準元素。(a)初始的序列和變數設定。沒有任何元素進入兩部分。(b)~(h)表示第3~6行的for迴圈的每一次重複。黑色雙向箭頭表示第6行的元素交換操作。(i)表示上述迴圈終止後第7行執行的元素交換操作。

partition(a, p, r)

1 x ← a[r]

2 i ← p - 1

3 for j ← p to r -1

4 do if a[j] ≤ x

5 then i ← i + 1

6 exchange a[i] ←→ a[j]

7 exchange a[i+1] ←→ a[r]

8 return i + 1

演算法:解決劃分問題的partition演算法
假定序列a[p...r]中含有n個元素。在此過程中,第3~6行的for迴圈重複了n次,所以該演算法的最壞執行時間為o(n)。

/** 

* @methodname:partition

* @description: 該方法用於序列的劃分

* @param a 用於儲存序列的陣列

* @param p 序列劃分的開始位置

* @param r 序列劃分的結束位置

* @return 序列劃分的分界點

*/ public static int partition(int a, int p, int r)

} //最後交換基準元素a[r]至第一部分尾部

swap(a, i+1, r);

//返回序列劃分的分界點位置i+1

return i+1; }

/**

* @methodname:swap

* @description: 用於交換序列中兩個位置的元素

* @param a 用於儲存序列的陣列

* @param p 要交換的第乙個元素的位置

* @param r 要交換的第二個元素的位置

*/ private static void swap(int a, int p, int r)

408真題 劃分序列

已知由n個正整數構成的集合a,將其劃分為兩個不想交的子集a1和a2,元素個數分別是n1和n2,a1和a2中的元素之和分別為s1和s2,設計乙個盡可能高效的演算法,滿足 n1 n2 最小且 s1 s2 最大。n2 n1最小即為兩子串行各為一半,且一半的所有元素比另外一半的任意元素都要小 此處可利用快速...

漸增型演算法三 劃分序列

目錄提供序列a p.r 要求以a r 為分界值,將原序列分兩部分 其中a p.q 1 中元素值小於分界值,a q 1.r 中的元素值大於分界值 返回新序列中的分界值下標q 說明 逐個比較序列值,若是其值大於分界值,則將其移到序列尾部,序列其他值前移 可能需要頻繁移動陣列,效率較低 int parti...

整數劃分(數的m劃分)

includeusing namespace std int f int n,int m n代表數字,m代表n的m劃分 int main 方式二 動態規劃 dp i j 表示i的j次劃分的情況種數 狀態轉移方程為dp i j dp i j j dp i 1 j 1 1.dp i 1 j 1 表示劃分...