[LeetCode] 53. Maximum SubArray
Posted codingEskimo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[LeetCode] 53. Maximum SubArray相关的知识,希望对你有一定的参考价值。
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.
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.
这道题要求两种解法,一种是O(N),一种是分支法O(nlogN)。其实这道题最暴力的解法是O(N2), 就是记住每一个起始位置的最大的值,显然,这不是这道题的要求。
思路一:O(N) 动态规划,想法很巧妙,
f(i) = f(i-1) > 0 ? f(i-1) + nums[i] : nums[i]
就是如果这个数之前的最大值如果是小于零的,你就重头开始,因为加了sum会变小,不如不加。如果大于零,那么就加上就。因为f(i)只和它之前的数字相关,进一步优化,就是之前的数的和的最大值加上现在这个数,再和现在这个数比较,更大,就加入,不然就舍弃之前的,只要现在这个数。
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
if not nums: return -sys.maxsize - 1
cur_sum, res = 0, -sys.maxsize - 1
for num in nums:
cur_sum = max(cur_sum + num, num)
res = max(cur_sum, res)
return res
思路二, 其实这个我理解的不是很好,先把解法写在这。想求一个数组的Max subarray,一共就是要考虑三种情况
- 左边数列的最大连续子集和
- 右边数列的最大连续子集和
- 有包含中间点的最大的连续子集和
前两种都很好写recursive,只要是只有一个点的时候就是出口,但第三种情况就比较复杂。要得到包括中间的最大子集,可以先求从左边到中间点的最大子集和,然后求从中间点向后一位到右边的最大子集和,最后相加即可。
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
if not nums: return -sys.maxsize-1
return self.find_max_subarray(nums, 0, len(nums) - 1)
def find_max_subarray(self, nums, left, right):
if left >= right: return nums[left]
mid = left + (right - left) // 2
left_sum = self.find_max_subarray(nums, left, mid)
right_sum = self.find_max_subarray(nums, mid+1, right)
crossing_sum = self.find_max_crossing_subarray(nums, left, right, mid)
return max(left_sum, right_sum, crossing_sum)
def find_max_crossing_subarray(self, nums, left, right, mid):
if left >= right: return nums[left]
left_sum, cur_sum = -sys.maxsize-1, 0
for i in range(mid, left-1, -1):
cur_sum += nums[i]
left_sum = max(left_sum, cur_sum)
right_sum, cur_sum = -sys.maxsize-1, 0
for i in range(mid+1, right+1):
cur_sum += nums[i]
right_sum = max(right_sum, cur_sum)
return left_sum + right_sum
以上是关于[LeetCode] 53. Maximum SubArray的主要内容,如果未能解决你的问题,请参考以下文章