[LeetCode解題攻略] 53. Maximum Subarray

更新 發佈閱讀 7 分鐘

題目描述

這道題是 LeetCode 的經典題之一,要求我們找出 一個子陣列,使其和最大,並返回這個最大和的數值。

題目要求

  • 給定一個數組 nums,找到一個具有最大和的 子陣列(subarray),並返回其最大和。

限制條件

  • 1 <= nums.length <= 10^5
  • -10^4 <= nums[i] <= 10^4

這表示我們要找 最優解法,因為 nums 可能非常大,暴力解法的 O(n²) 可能會超時。


範例

範例 1:

輸入: nums = [-2,1,-3,4,-1,2,1,-5,4]
輸出: 6
解釋: 最大子陣列為 [4, -1, 2, 1],其和為 4 + (-1) + 2 + 1 = 6

範例 2:

輸入: nums = [1]
輸出: 1
解釋: 只有一個數,所以答案就是 1

範例 3:

輸入: nums = [5,4,-1,7,8]
輸出: 23
解釋: 最大子陣列為 [5, 4, -1, 7, 8],其和為 23

解題思路

思路 1:暴力解法

  • 遍歷所有可能的子陣列,計算總和,找出最大值。
  • 這種方法的時間複雜度為 O(n²),不可行。

思路 2:Kadane's Algorithm(動態規劃)

  • 使用 動態規劃(Dynamic Programming),透過 dp[i] 存儲 nums[i] 為結尾的最大子陣列和,然後找出最大值。
  • 這種方法的時間複雜度為 O(n),適合大數據量。

思路 3:分治法(Divide and Conquer)

  • 運用遞迴方式,將陣列分成左、右兩部分,然後合併解決。
  • 這種方法的時間複雜度為 O(n log n)

解法一:暴力枚舉

思路

  1. 遍歷 nums 的所有 子陣列,計算其總和。
  2. 找出 最大的總和 並返回。

程式碼

class Solution:
def maxSubArray(self, nums: List[int]) -> int:
max_sum = float('-inf')
n = len(nums)
for i in range(n):
current_sum = 0
for j in range(i, n):
current_sum += nums[j]
max_sum = max(max_sum, current_sum)
return max_sum

時間與空間複雜度

  • 時間複雜度:O(n²)
    • 內部雙層迴圈,每次都要計算新的子陣列總和,會超時。
  • 空間複雜度:O(1)
    • 只使用了 max_sum 和 current_sum,額外空間需求為 O(1)。

解法二:Kadane's Algorithm(動態規劃)

思路

  1. 使用 current_sum 來記錄 當前以 nums[i] 為結尾的最大子陣列和
  2. 如果 current_sum 變成負數,則 從下一個數字重新開始(因為負數會降低總和)。
  3. 同時維護 max_sum,確保記錄到最大的結果。

程式碼

class Solution:
def maxSubArray(self, nums: List[int]) -> int:
max_sum = nums[0]
current_sum = nums[0]
for i in range(1, len(nums)):
current_sum = max(nums[i], current_sum + nums[i])
max_sum = max(max_sum, current_sum)
return max_sum

時間與空間複雜度

  • 時間複雜度:O(n)
    • 只需一次遍歷 nums,每個元素只計算一次。
  • 空間複雜度:O(1)
    • 只使用了 current_sum 和 max_sum,不需要額外空間。

解法三:分治法(Divide and Conquer)

思路

  1. 拆分陣列,分為 左部分右部分橫跨中點的最大子陣列
  2. 遞迴計算左、右部分的最大子陣列和。
  3. 計算包含中點的最大子陣列和(透過從中點開始向左、向右擴展)。
  4. 返回三者之間的最大值。

程式碼

class Solution:
def maxSubArray(self, nums: List[int]) -> int:
def divide_and_conquer(left, right):
if left == right:
return nums[left]

mid = (left + right) // 2
left_sum = divide_and_conquer(left, mid)
right_sum = divide_and_conquer(mid + 1, right)

cross_sum = find_cross_sum(nums, left, right, mid)

return max(left_sum, right_sum, cross_sum)

def find_cross_sum(nums, left, right, mid):
left_max = float('-inf')
right_max = float('-inf')

sum_temp = 0
for i in range(mid, left - 1, -1):
sum_temp += nums[i]
left_max = max(left_max, sum_temp)

sum_temp = 0
for i in range(mid + 1, right + 1):
sum_temp += nums[i]
right_max = max(right_max, sum_temp)

return left_max + right_max

return divide_and_conquer(0, len(nums) - 1)

時間與空間複雜度

  • 時間複雜度:O(n log n)
    • 由於每次遞迴都將問題劃分為兩半,類似於歸併排序,因此時間複雜度為 O(n log n)。
  • 空間複雜度:O(log n)
    • 由於使用遞迴,每層遞迴佔用 O(log n) 的空間。

結論

這題是一道經典的動態規劃問題,適合用 Kadane's Algorithm 來解,因為它的 O(n) 時間複雜度 適合大數據量。


留言
avatar-img
追極光的北極熊|軟體工程師的小天地
13會員
169內容數
歡迎來到我的部落格!這裡記錄了軟體工程師的日常生活點滴,並分享程式設計與演算法的實用教學。無論你是初學者還是有經驗的開發者,都能在這裡找到深入淺出的技術解析與實戰技巧。此外,我也會分享工作中的心路歷程與學習心得,讓你不僅學到技術,更能瞭解軟體開發的實際應用與挑戰。希望透過這個平台,能與你共同成長,激發對技術的熱情!
2025/04/04
給定一個非負整數陣列 nums,其中 nums[i] 代表你在索引 i 處最多可以向右跳幾步。 請判斷是否能夠從索引 0 跳到最後一個索引。
2025/04/04
給定一個非負整數陣列 nums,其中 nums[i] 代表你在索引 i 處最多可以向右跳幾步。 請判斷是否能夠從索引 0 跳到最後一個索引。
2025/03/28
給定一個 m x n 的矩陣 matrix,請按照 螺旋順序(spiral order) 返回矩陣中的所有元素。
2025/03/28
給定一個 m x n 的矩陣 matrix,請按照 螺旋順序(spiral order) 返回矩陣中的所有元素。
2025/03/18
52. N-Queens II 題目是經典的組合優化問題,它要求解出一個 n x n 的棋盤上,放置 n 個皇后,且要求皇后們不互相攻擊,並計算出所有合法的解的數量。
2025/03/18
52. N-Queens II 題目是經典的組合優化問題,它要求解出一個 n x n 的棋盤上,放置 n 個皇后,且要求皇后們不互相攻擊,並計算出所有合法的解的數量。
看更多
你可能也想看
Thumbnail
vocus 慶祝推出 App,舉辦 2026 全站慶。推出精選內容與數位商品折扣,訂單免費與紅包抽獎、新註冊會員專屬活動、Boba Boost 贊助抽紅包,以及全站徵文,並邀請你一起來回顧過去的一年, vocus 與創作者共同留下了哪些精彩創作。
Thumbnail
vocus 慶祝推出 App,舉辦 2026 全站慶。推出精選內容與數位商品折扣,訂單免費與紅包抽獎、新註冊會員專屬活動、Boba Boost 贊助抽紅包,以及全站徵文,並邀請你一起來回顧過去的一年, vocus 與創作者共同留下了哪些精彩創作。
Thumbnail
Leetcode 精選75題 題目與題解 熱門考點 目錄 (持續更新中) 建議從左側目錄 或者 按Ctrl+F輸入關鍵字進行搜尋
Thumbnail
Leetcode 精選75題 題目與題解 熱門考點 目錄 (持續更新中) 建議從左側目錄 或者 按Ctrl+F輸入關鍵字進行搜尋
Thumbnail
題目會給定一個陣列nums和一個目標值goal。計算子陣列總和=goal的數目有多少。演算法包含前綴和和字典的技巧,時間複雜度為O(n),空間複雜度為O(n)。
Thumbnail
題目會給定一個陣列nums和一個目標值goal。計算子陣列總和=goal的數目有多少。演算法包含前綴和和字典的技巧,時間複雜度為O(n),空間複雜度為O(n)。
Thumbnail
題目敘述 題目會給定我們一個輸入陣列nums,要求我們掃描美個陣列元素nums[i],計算除了nums[i]以外的陣列元素連乘積。 題目的原文敘述 測試範例 Example 1: Input: nums = [1,2,3,4] Output: [24,12,8,6] nums[0] 以
Thumbnail
題目敘述 題目會給定我們一個輸入陣列nums,要求我們掃描美個陣列元素nums[i],計算除了nums[i]以外的陣列元素連乘積。 題目的原文敘述 測試範例 Example 1: Input: nums = [1,2,3,4] Output: [24,12,8,6] nums[0] 以
Thumbnail
題目敘述 題目會給定一個二元陣列nums(也就是說,陣列元素只有0,1這兩種情況)。 我們必須從裡面選擇一個元素刪除之後,請問連續為1的最長子陣列的長度是多少? 測試範例 Example 1: Input: nums = [1,1,0,1] Output: 3 Explanation:
Thumbnail
題目敘述 題目會給定一個二元陣列nums(也就是說,陣列元素只有0,1這兩種情況)。 我們必須從裡面選擇一個元素刪除之後,請問連續為1的最長子陣列的長度是多少? 測試範例 Example 1: Input: nums = [1,1,0,1] Output: 3 Explanation:
Thumbnail
題目敘述 題目會給定一個二元陣列nums(也就是說,陣列元素只有0,1這兩種情況)和指定的k值。 我們最多可以把k個0反轉成1,請問連續唯一的最長子陣列的長度是多少? 題目的原文敘述 測試範例 Example 1: Input: nums = [1,1,1,0,0,0,1,1,1,1,
Thumbnail
題目敘述 題目會給定一個二元陣列nums(也就是說,陣列元素只有0,1這兩種情況)和指定的k值。 我們最多可以把k個0反轉成1,請問連續唯一的最長子陣列的長度是多少? 題目的原文敘述 測試範例 Example 1: Input: nums = [1,1,1,0,0,0,1,1,1,1,
Thumbnail
題目敘述 題目會給定一個有n個整數的陣列nums和指定的k值,問我們長度為k的子陣列的平均值的最大值是多少? 題目的原文敘述 測試範例 Example 1: Input: nums = [1,12,-5,-6,50,3], k = 4 Output: 12.75000 Explanati
Thumbnail
題目敘述 題目會給定一個有n個整數的陣列nums和指定的k值,問我們長度為k的子陣列的平均值的最大值是多少? 題目的原文敘述 測試範例 Example 1: Input: nums = [1,12,-5,-6,50,3], k = 4 Output: 12.75000 Explanati
Thumbnail
題目敘述 題目會給兩個陣列nums1和nums2。 題目要求我們從中同步選擇長度為k的子序列,並且最大化子序列的分數, 回傳最高的分數值。 分數的定義: 分數 = (nums1[i0] + nums1[i1] +...+ nums1[ik - 1]) * min(nums2[i0] ,
Thumbnail
題目敘述 題目會給兩個陣列nums1和nums2。 題目要求我們從中同步選擇長度為k的子序列,並且最大化子序列的分數, 回傳最高的分數值。 分數的定義: 分數 = (nums1[i0] + nums1[i1] +...+ nums1[ik - 1]) * min(nums2[i0] ,
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News