题目
Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.
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.
Example 1:
Input: nums = [-2,1,-3,4,-1,2,1,-5,4]
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.
Example 2:
Input: nums = [1]
Output: 1
Example 3:
Input: nums = [0]
Output: 0
Example 4:
Input: nums = [-1]
Output: -1
Example 5:
Input: nums = [-2147483647]
Output: -2147483647
Constraints:
1 <= nums.length <= 2 * 104
-2^31 <= nums[i] <= 2^31 - 1
动态规划解法
题意是求数组中子数组的最大和,这种最优问题一般第一时间想到的就是动态规划,我们可以这样想,当部分序列和大于零的话就一直加下一个元素即可,并和当前最大值进行比较,如果出现部分序列小于零的情况,那肯定就是从当前元素算起。其转移方程就是 dp[i] = nums[i] + (dp[i - 1] > 0 ? dp[i - 1] : 0);,由于我们不需要保留 dp 状态,故可以优化空间复杂度为 1,即 dp = nums[i] + (dp > 0 ? dp : 0);。
class MaxmumSubarray:
def maxSubArray(self, nums: List[int]) -> int:
if nums == None or len(nums) == 0:
return 0
for i in range(1, len(nums)):
if nums[i - 1] > 0:
nums[i] += nums[i - 1]
return max(nums)
分而治之解法
题目也给了我们另一种思路,就是分治,所谓分治就是把问题分割成更小的,最后再合并即可,我们把 nums 一分为二先,那么就有两种情况,一种最大序列包括中间的值,一种就是不包括,也就是在左边或者右边;当最大序列在中间的时候那我们就把它两侧的最大和算出即可;当在两侧的话就继续分治即可。
class MaxmumSubarray:
def maxSubArray(self, nums: List[int]) -> int:
return self.helper(nums, 0, len(nums) - 1)
def helper(self, nums: List[int], left: int, right: int) -> int:
if left >= right:
return nums[left]
mid = (int)((left + right) / 2)
leftSub = self.helper(nums, left, mid)
rightSub = self.helper(nums, mid+1, right)
leftMax = nums[mid]
rightMax = nums[mid + 1]
temp = 0
for i in range(mid, left - 1, -1):
temp += nums[i]
if temp > leftMax:
leftMax = temp
temp = 0
for k in range(mid+1, right + 1):
temp += nums[k]
if temp > rightMax:
rightMax = temp
return max(max(leftSub, rightSub), leftMax + rightMax)