有乙個非分治策略的處理最大子陣列的問題,該解法更優雅簡潔,並更高效。之所以專門去寫分治法是為了更好地理解樹形結構。
該方法的核心思想就是當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的定義為邊界與和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;
}
findmaximumsubarray()則為分解與合併的部分struct node
;
初始呼叫函式findmaximumsubarray()會求出a[1…n]的最大子陣列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;
}
輸入:#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 已經排序好了,現在將這兩個排序好的部分陣列再排序,每次比較兩個子陣列的頭元素大小,小的插入,然後出佇列。因為有哨兵的存在,所以一定能排完。純翻譯...