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) 的解法,定义两个变量 res 和 curSum,其中 res 保存最终要返回的结果,即最大的子数组之和。curSum 初始值为0,每遍历一个数字 num,比较 curSum + num 和 num 中的较大值存入 curSum,然后再把 res(保存的是上一次curSum和res的最大值) 和 curSum 中的较大值存入 res,以此类推直到遍历完整个数组,可得到最大子数组的值存在 res 中,代码如下:
from typing import List
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
if len(nums) == 0:
return 0
else:
curSum = 0
res = 0
for num in nums:
curSum = max(curSum+num,num)
res = max(res, curSum)
return res
nums = [-2,1,-3,4,-1,2,1,-5,4]
solution = Solution()
solution.maxSubArray(nums)
# list
from typing import List
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
if len(nums) == 0:
return 0
else:
curSum = [0 for i in range(len(nums))] #长度为len(nums)值为0的list
curSum.append(nums[0])
res = curSum[0]
for i in range(1,len(nums)):
curSum[i] = max(curSum[i-1]+nums[i],nums[i])
res = max(res, curSum[i])
return res
nums = [-2,1,-3,4,-1,2,1,-5,4]
solution = Solution()
solution.maxSubArray(nums)
分治法 Divide and Conquer Approach:
其思想类似于二分搜索法,需要把数组一分为二,分别找出左边和右边的最大子数组之和,然后还要从中间开始向左右分别扫描,求出的最大值分别和左右两边得出的最大值相比较取最大的那一个,代码如下:
from typing import List
class Solution(object):
def maxSubArray(self, nums: List[int]) -> int:
"""
:type nums: List[int]
:rtype: int
"""
return self.divideMethod(nums, 0, len(nums) - 1)
def divideMethod(self, nums, i, j):
if i == j:
return nums[i]
divide = (i + j) // 2
ls = nums[divide]
rs = nums[divide + 1]
# left
sum = 0
for k in range(divide + 1, j + 1):
sum += nums[k]
if sum >= rs:
rs = sum
# right
sum = 0
for k in range(divide, i - 1, -1):
sum += nums[k]
if sum >= ls:
ls = sum
maxSum = ls + rs
leftMaxSum = self.divideMethod(nums, i, divide)
rigthMaxSum = self.divideMethod(nums, divide + 1, j)
if leftMaxSum >= maxSum:
maxSum = leftMaxSum
if rigthMaxSum >= maxSum:
maxSum = rigthMaxSum
return maxSum
nums = [-2,1,-3,4,-1,2,1,-5,4]
solution = Solution()
solution.maxSubArray(nums)
动态规划:
将求n个数的数组的最大子段和,转换为分别求出以第1个、第2个、…第i个、…、第n个数字结尾的最大字段和,再找出这n个结果中最大的,即为结果。
第i个状态(dp[i])即为以第i个数字结尾的最大子段和(最优解)。由于以第i-1个数字结尾的最大子段和(dp[i-1])与nums[i]相邻:
# 动态规划
from typing import List
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
if len(nums) == 0:
return 0
else:
dp = [0 for i in range(len(nums))] # 长度为len(nums)值为0的list
dp.append(nums[0])
maxnum = dp[0]
for i in range(1,len(nums)):
dp[i] = max(dp[i-1]+nums[i],nums[i])
if dp[i] > maxnum:
maxnum = dp[i]
return maxnum
nums = [-2,1,-3,4,-1,2,1,-5,4]
solution = Solution()
solution.maxSubArray(nums)
(仔细想想和遍历法是一样的)