【演算法導論】最大子陣列問題的三種解法
標籤(空格分隔):【演算法導論】
首先補充兩個數學公式:
a lo
gbc=
clog
baa^ = c^
alogb
c=cl
ogbalo
g(n!
)=θ(
nlog
n)log(n!) = \theta(nlogn)
log(n!
)=θ(
nlog
n)什麼是最大子陣列問題?
給定一陣列a, 尋找a中和最大的非空連續子陣列。
例如:輸入: a = [-2,1,-3,4,-1,2,1,-5,4],
輸出: 6
解釋: 連續子陣列 [4,-1,2,1] 的和最大為 6。
針對該問題,現給出三種解法。
解法一:暴力求解(最直觀的方法)
對於長度為 n 的陣列a, 任選兩個位置作為區間起始和末尾,計算該區間所代表的的子陣列的和,選擇最大的乙個。
符合條件的位置對數有cn2
c_n^2
cn2
個,因此時間複雜度為o(n
2)o(n^2)
o(n2).
由於計算區間和時需要借助乙個輔助陣列,因此空間複雜度為o(n
)o(n)
o(n)
**:
int find_max_subarray( vector& a)
解法二:分治演算法(不好理解且**長)
假設將陣列a[low, …, high] 以位置mid處劃分為兩個長度大致相等的子陣列,則最大子陣列a[i, …, j] 必定為以下三種情況之一:
最大子陣列完全位於 a[low, …, mid] 之間,即 low
≤i≤j
≤mid
low \le i \le j \le mid
low≤i≤
j≤mi
d.最大子陣列完全位於 a[mid, …, high] 之間,即 mid
≤i≤j
≤hig
hmid \le i \le j \le high
mid≤i≤
j≤hi
gh.最大子陣列跨越了 mid 位置,即 low
≤i≤m
idhigh
low \le i \le mid < j \le high
low≤i≤mid
high
. **:
int find_max_subarray( vector& a, int left, int right)
sum = sum_max; // 向另外一側移動時需要初始化
for( int i = mid + 1; i <= right; i++)
return max( max( l, r), sum_max);
}// 在主程式中輸入的引數應該為 find_max_subarray(a, 0, a.size() - 1)測試用例:
注:改**已ac leetcode 第53題。
時間複雜度為:o(n
logn
)o(nlogn)
o(nlog
n)解法三:動態規劃(不易理解但短小精悍)
初始化變數 sum = 0, 從頭遍歷陣列,對於每乙個元素 a[i], 變數 sum += a[i], 一旦 sum < 0, 立即讓 sum = 0, 並向後移動乙個元素,直到陣列尾部。最終選擇最大的 sum 值。
為直觀起見,以陣列 a = [-2, 3, -1, 2, -3] 為例:
}測試用例:
注:改**已ac leetcode 第53題。
由於只是遍歷陣列,因此時間複雜度為 o(n
演算法導論之三最大子陣列問題
最大子陣列是陣列a的和最大的非空連續子陣列。只有當陣列中包含負數時,最大子陣列問題才有意義。注意將實際問題轉化為數學問題!使用分治策略的求解方法 為尋找a low.high 的最大子陣列,其 位置記為mid,然後考慮求解兩個子陣列a low.mid 和a mid 1.high a low.high ...
最大子陣列問題 演算法導論
分治法思想 分解 子陣列一定被原陣列左邊或者右邊包含,或者跨越原陣列mid下標。解決 前兩種完全包含的情況形成子問題遞迴求解,並且縮小了問題規模,後一種是我們要解決的問題。合併 剩餘的問題是求跨越mid的最大子陣列,並且從三種情況中選出和最大的。另外 算導中偽 返回的是三元組,這裡實現的話用結構體返...
最大子陣列問題的三種解法
最大子陣列問題 在乙個數列當中尋找乙個子數列,使得這個子數列的元素之和最大。為了使 簡單化,在這裡我們只求出最大值。暴力搜尋,即在c n,2 種可能的方法中尋找符合題意得一種,顯然時間複雜度為 n include include using namespace std int a 16 int ma...