演算法導論的C 實現 2 分治策略處理最大子陣列

2021-10-25 01:32:47 字數 3459 閱讀 8439

有乙個非分治策略的處理最大子陣列的問題,該解法更優雅簡潔,並更高效。之所以專門去寫分治法是為了更好地理解樹形結構。

該方法的核心思想就是當sum小於零就捨棄當前sum,有個小bug就是全為負數,不過很好解決,一下是源**:

//線性求最大子區間

#include

using

namespace std;

constexpr

int maxn =

200;

const

int inf =

0x3f3f3f3f

;int

main()

int sum =0;

int maxa =

-inf;

for(

int i =

1; i <= n; i++)if

(sum <0)

} cout << maxa << endl;

return0;

}

a[low…high]的任何連續子陣列a[i…j]所處的位置必然是一下三種情況之一:

完全位於子陣列a[low…mid]中,因此low<=i<=j<=mid

完全位於子陣列a[mid+1…high]中,因此mid過程findmaxcrossingsubarray接受兩個引數l和r,返回乙個結構體劃定跨越中點的最大子陣列的邊界,並返回最大子陣列中值的和。

node findmaxcrossingsubarray

(int l,

int r)

}int rightsum =

-inf;

sum =0;

for(

int i = mid +

1; i <= r; i++)}

node rten;

rten.left = maxleft;

rten.right = maxright;

rten.sum = leftsum + rightsum;

return rten;

}

其中node的定義為邊界與和

struct node 

;

findmaximumsubarray()則為分解與合併的部分

node findmaximumsubarray

(int l,

int r)

int mid =

(l + r)

>>1;

leftnum =

findmaximumsubarray

(l, mid)

; rightnum =

findmaximumsubarray

(mid +

1, r)

; crossnum =

findmaxcrossingsubarray

(l, r);if

(leftnum.sum >= rightnum.sum && leftnum.sum >= crossnum.sum)

return leftnum;

else

if(rightnum.sum >= leftnum.sum && rightnum.sum >= crossnum.sum)

return rightnum;

else

return crossnum;

}

初始呼叫函式findmaximumsubarray()會求出a[1…n]的最大子陣列

#include

#include

using

namespace std;

constexpr

int maxn =

200;

constexpr

int inf =

0x3f3f3f3f

;int a[maxn]

;struct node

;node findmaxcrossingsubarray

(int left,

int right)

;node findmaximumsubarray

(int left,

int right)

;int

main()

node ans;

ans =

findmaximumsubarray(1

, n)

; cout <<

"max left = "

<< ans.left <<

"max right = "

<< ans.right <<

"sum = "

<< ans.sum << endl;

return0;

}node findmaxcrossingsubarray

(int l,

int r)

}int rightsum =

-inf;

sum =0;

for(

int i = mid +

1; i <= r; i++)}

node rten;

rten.left = maxleft;

rten.right = maxright;

rten.sum = leftsum + rightsum;

return rten;

}node findmaximumsubarray

(int l,

int r)

int mid =

(l + r)

>>1;

leftnum =

findmaximumsubarray

(l, mid)

; rightnum =

findmaximumsubarray

(mid +

1, r)

; crossnum =

findmaxcrossingsubarray

(l, r);if

(leftnum.sum >= rightnum.sum && leftnum.sum >= crossnum.sum)

return leftnum;

else

if(rightnum.sum >= leftnum.sum && rightnum.sum >= crossnum.sum)

return rightnum;

else

return crossnum;

}

輸入

1613 -3 -25 20 -3 -16 -23 18 20 -7 12 -5 -22 15 -4 7

輸出

max left = 8max right = 11sum = 43

《演算法導論》 2 3 1分治法

分治法 有很多演算法在結構上是遞迴的 為了解決乙個給定的問題,演算法要一次或多次地遞迴地呼叫其自身來解決相關的問題。這些演算法通常採用分治策略 將原問題劃分為n個規模較小而結構與原問題相似的子總是 遞迴地解決這些子問題,然後再合併其結果,就得到原問題的解。分治模式在每一層遞迴上都有三個步驟 分解 d...

演算法導論 第四章 分治策略 (6)分治策略概述

當子問題足夠大,需要遞迴求解時,稱之為遞迴情況。當子問題變得足夠小,不再需要遞迴時,我們說遞迴已經 觸底 進入了基本情況。遞迴式與分治方法是緊密相關的,因為使用遞迴式可以很自然的刻畫分治演算法的執行時間。乙個遞迴式就是乙個等式或不等式,它通過更小的輸入上的函式值來描述乙個函式。子問題的規模不必是原問...

演算法導論學習筆記 2 3 1分治法(歸併排序)

純翻譯 void merge ll a ll p,ll q,ll r else merge函式解析 假設a陣列的兩部分 乙個下標從p到q,乙個從q 1到r 已經排序好了,現在將這兩個排序好的部分陣列再排序,每次比較兩個子陣列的頭元素大小,小的插入,然後出佇列。因為有哨兵的存在,所以一定能排完。純翻譯...