1.题目
原题链接
https://leetcode-cn.com/problems/contiguous-sequence-lcci/
题目描述
给定一个整数数组,找出总和最大的连续数列,并返回总和。
示例
输入: [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
2.算法
方法1 动态规划
思路与算法
- 记 d p [ i ] dp[i] dp[i]为以 n u m s [ i ] nums[i] nums[i]结尾的最大连续子序列
- 若 n u m s [ i ] ≥ 0 nums[i] \ge 0 nums[i]≥0,则 d p [ i ] = d p [ i − 1 ] + n u m s [ i ] dp[i] = dp[i - 1] + nums[i] dp[i]=dp[i−1]+nums[i]
- 否则, d p [ i ] = n u m s [ i ] dp[i] = nums[i] dp[i]=nums[i]
- 结果返回 d p dp dp中最大的元素
代码
class Solution:
def maxSubArray(self, nums):
n = len(nums)
dp = [num for num in nums]
for i in range(1, n):
if nums[i] >= 0:
dp[i] = dp[i - 1] + nums[i]
else:
dp[i] = nums[i]
return max(dp)
复杂度
- 时间复杂度: O ( N ) O(N) O(N)
- 空间复杂度: O ( N ) O(N) O(N)
方法2 递归
思路与算法
递归计算左半部分的最大连续和,最右部分的最大连续和以及中间部分的最大连续和,结果为其中的最大者。
代码
class Solution:
def maxSubArray(self, nums):
def divide(nums, left, right):
if left == right:
return nums[left]
mid = left + (right - left) // 2
# 左半部分的最大和
sum_left = divide(nums, left, mid)
# 右半部分的最大和
sum_right = divide(nums, mid + 1, right)
# 求中间部分的最大和
# 先求中间偏左部分的最大和
left_sum, max_left_sum = 0, -99999
for i in range(mid, left - 1, -1):
left_sum += nums[i]
max_left_sum = max(left_sum, max_left_sum)
# 再求中间偏右部分的最大和
right_sum, max_right_sum = 0, -99999
for i in range(mid + 1, right + 1):
right_sum += nums[i]
max_right_sum = max(right_sum, max_right_sum)
return max(sum_left, sum_right, max_left_sum + max_right_sum)
if not nums or len(nums) == 0:
return 0
return divide(nums, 0, len(nums) - 1)
复杂度
- 时间复杂度:??(有点迷糊,有没有哪个网友知道呢?)
- 空间复杂度:递归要占用系统栈,由于递归数高为 O ( l o g N ) O(logN) O(logN),所有空间复杂度为 O ( l o g N ) O(logN) O(logN)