0053. Maximum Subarray - chasel2361/leetcode GitHub Wiki
Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.
Example:
Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.
這個問題我也只想得到硬幹的從頭數,會長這樣
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
m = -10**10
for i in range(len(nums)):
for j in range(i, len(nums)):
total = sum([nums[n] for n in range(i, j + 1)])
if total > m:
m = total
return m
可是這個解法的時間複雜度相當高,應該是O(N^2),所以來看看雨蕭大大的寫法
他介紹了一個概念:動態規劃
動態規劃演算法的核心在於記住已經解決過的子問題的解
動態規劃的精神是,把一個大問題拆分成許多相依的小問題,當解決所有小問題之後就能順勢解決大問題。
這個題目的主要問題是,找到陣列中總和最大的連續子陣列。
此時可以衍生出兩個子問題:
- 怎麼找到子陣列的總和?
- 各個子陣列如何比大小?
為了解決這兩個問題,可以定義兩個變數:
- curr:當前選取之子陣列總和
- res:目前為止最大子陣列總和
[1] 如果當前選取子陣列總和大於零,則擴充子陣列
[2] 如果當前選取子陣列總和不大於零,則更新子陣列 (總和不大於零就沒有擴充的意義了)
[3] 將當前子陣列總和與最大子陣列總和比較
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
l = len(nums)
if l == 0: return 0
res = cur = nums[0]
for i in range(1, l):
if cur > 0:
cur += nums[i] # [1]
else:
cur = nums[i] # [2]
if cur > res:
res = cur
return res
由於題目要求連續子陣列,所以能夠使用這樣的方式來不停更新子陣列,此法的時間複雜度可以大幅降低到O(N),空間複雜度是O(2)
參考了其他人的寫法之後,發現另一個概念一樣,但較為精簡的寫法:
把各式子陣列存在陣列裡,最後再回傳其中的最大值。
這個寫法少了一個判斷,時間複雜度仍然是O(N),但空間複雜度是O(N),較原本的方法稍大。
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
dp = [0] * len(nums)
dp[0] = nums[0]
for i in range(1, len(nums)):
dp[i] = nums[i] + (dp[i - 1] if dp[i - 1] > 0 else 0)
"""上面這行相當於下方程式碼
if dp[i - 1] > 0:
dp[i] = nums[i] + dp[i - 1]
else:
dp[i] = nums[i]
"""
return max(dp)