最大子序和分治
最大子序和(Maximum Subarray Problem)是一個經典的動態規劃問題,其目標是找到一個數組中的最大子序和。子序和是指數組中連續元素的 sum。例如,對於數組 [2, 11, -4, 13, -5, 5]
,其最大子序和為 11 + -4 + 13 + -5 + 5 = 10
。
分治是一種算法設計範式,它將問題分解為更小的、相似的子問題,直到達到最簡單的子問題,然後通過組合這些子問題的解決方案來解決原始問題。對於最大子序和問題,我們可以使用分治策略來設計一個高效的算法。
下面是一個使用分治策略解決最大子序和問題的算法:
-
首先,我們定義一個遞歸函式
maxSubArray
,它接受一個數組nums
和一個開始索引start
以及結束索引end
作為參數。 -
我們通過以下步驟來解決這個問題:
- 如果
start == end
,那么子問題的答案就是數組nums
中的單個元素。 - 否則,我們找到中間索引
mid = (start + end) / 2
,並將子問題劃分為兩個更小的子問題。 - 我們遞歸地解決左半部分和右半部分的問題,分別計算它們的最大子序和。
- 我們比較左半部分和右半部分的結果與直接在
nums[start...end]
上計算的最大子序和。這個可以通過從nums[start]
開始累加和來計算,同時維護一個當前最大值。 - 我們返回這三個值中的最大值作為子問題的答案。
- 如果
下面是偽代碼:
def maxSubArray(nums, start, end):
if start == end:
return nums[start]
mid = (start + end) // 2
left_max = maxSubArray(nums, start, mid)
right_max = maxSubArray(nums, mid + 1, end)
current_max = helper(nums, start, end)
return max(left_max, right_max, current_max)
def helper(nums, start, end):
current_sum = nums[start]
max_ending_here = nums[start]
for i in range(start + 1, end + 1):
current_sum = max(current_sum + nums[i], 0)
max_ending_here = max(max_ending_here, current_sum)
return max_ending_here
這個算法的時間複雜度為 O(n log n),因為每個元素都會被訪問 O(log n) 次。空間複雜度為 O(n),因為遞歸調用棧的大小與數組的大小成正比。
在實際套用中,通常使用 Kadane's algorithm 來解決最大子序和問題,它的時間複雜度為 O(n),空間複雜度為 O(1),因為它是使用動態規劃線上性時間內解決的。