53. Maximum Subarray
Easy
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.
方法1:动态规划 O(n)
设dp[i]为以索为i结尾的子串的和的最大值
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
last_num = nums[0]
max_num = last_num
for i in range(1, len(nums)):
if last_num > 0:
last_num += nums[i]
else:
last_num = nums[i]
max_num = max(max_num, last_num)
return max_num
方法2:分治 O(n*logn)
将数组平均分为两部分,最大子数组存在于:
- 左侧数组的最大子数组
- 右侧数组的最大子数组
- 以左侧数组为起点向左的最大子数组+以右侧数组为起点向右的最大子数组
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
return self.subArray(nums, 0, len(nums) - 1)
def subArray(self, nums: List[int], l: int, r: int) -> int:
if l == r:
return nums[l]
mid = (l + r + 1) // 2
left_max = self.subArray(nums, l, mid - 1)
right_max = self.subArray(nums, mid, r)
temp = 0
left = nums[mid - 1]
for i in range(mid - 1, l - 1, -1):
temp += nums[i]
left = max(left, temp)
right = nums[mid]
temp = 0
for i in range(mid, r + 1):
temp += nums[i]
right = max(right, temp)
return max(left_max, right_max, left + right)
方法3:Kadane算法 O(n)
该算法的核心思想是,最大子片段不可能包含求和值为负的前缀。
当我们每次累加得到的当前序列的和小于0时,那么下一个数开始的序列可能是一个最大的序列,我们需要把序列和清零(max_end_here),下面的两个if语句顺序不能反过来,不然当全部为负数时,就会出错。
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
max_end_here = 0
max_so_far = nums[0]
for i in range(len(nums)):
max_end_here += nums[i]
if max_so_far < max_end_here:
max_so_far = max_end_here
if max_end_here < 0:
max_end_here = 0
return max_so_far