Problem
Given an integer array nums
, find the
subarray
with the largest sum, and return
its sum
.
Example 1:
1 2 3 4
| Input: nums = [-2,1,-3,4,-1,2,1,-5,4] Output: 6 Explanation: The subarray [4,-1,2,1] has the largest sum 6.
|
Example 2:
1 2 3 4
| Input: nums = [1] Output: 1 Explanation: The subarray [1] has the largest sum 1.
|
Example 3:
1 2 3 4
| Input: nums = [5,4,-1,7,8] Output: 23 Explanation: The subarray [5,4,-1,7,8] has the largest sum 23.
|
Constraints:
1 <= nums.length <= 10^5
10^4 <= nums[i] <= 10^4
Follow up: If you have figured out the O(n)
solution, try coding another solution using the divide and conquer approach, which is more subtle.
Solve
法1
原理就是每次作判別,計算當前最大的,和nums[ i ]比較原因是,代表nums[ i ],比前面都大
e.g.
nums =[1,-1,0,-1,1]
⇒dp =[1, 0, 0, -1, 1]
nums =[-1 ,-2 ,0]
⇒dp =[-1, -2, 0]
nums =[5,4,-1,7,8]
⇒dp =[5, 9, 8, 15, 23]
1 2 3 4 5 6 7 8
| 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] = max(dp[i-1]+nums[i],nums[i])
return max(dp)
|
Time Complexity: O(N)
Space Complexity:O(N)
這邊可以改成兩個變數,currMax、sumMax,這樣Space Complexity 可降為O(1)
1 2 3 4 5 6 7 8
| class Solution: def maxSubArray(self, nums: List[int]) -> int: currMax = 0 sumMax= float('-inf') for num in nums: currMax = max(num, num + currMax) sumMax= max(currMax, sumMax) return sumMax
|
Time Complexity: O(N)
Space Complexity:O(1)
法2
看到奇怪的方法,但是可以順便練習 D&C
題目說除了O(n) 還有利用divide and conquer 的解,關鍵就是拆分→計算→合併
在遞迴時,
1 2 3 4 5 6
| [整串數列] / | \ [左半部分] [中間部分] [右半部分] / | \ / | \ / | \ [左] [中] [右] [左] [中] [右] [左] [中] [右] ... ... ...
|
拆成
三部分 左 中 右
計算
左右遍歷,中的最大值
合併
Max(左 ,中 ,右)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| class Solution: def maxSubArray(self, nums: List[int]) -> int: def maxCrossingSum(nums, low, mid, high): left_sum = float('-inf') right_sum = float('-inf') max_left = 0 max_right = 0
for i in range(mid, low - 1, -1): max_left += nums[i] if max_left > left_sum: left_sum = max_left for i in range(mid + 1, high + 1): max_right += nums[i] if max_right > right_sum: right_sum = max_right
return left_sum + right_sum
def findMaxSubArray(nums, low, high): if low == high: return nums[low]
mid = (low + high) // 2
left_max = findMaxSubArray(nums, low, mid) right_max = findMaxSubArray(nums, mid + 1, high)
cross_max = maxCrossingSum(nums, low, mid, high)
return max(left_max, right_max, cross_max)
if not nums: return 0
return findMaxSubArray(nums, 0, len(nums) - 1)
|
拆分到最後,每個都會當中心點→
計算往左往右擴,當下為中心最大值→
往上返回, 區間最大 = 子區間最大 →
答案
Time Complexity: O(nlogn)
Space Complexity:O(logn) #主要來自 遞迴的