题目
给定一个整数数组 nums
,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例 :
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
进阶:
如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。
自己的想法
算法实现
class Solution:
def maxSubArray(nums: List[int]) -> int:
lenth = len(nums)
max = float("-inf")
sum = 0
i = 0
while i != lenth:
if sum == 0 and nums[i] <= 0:
sum = nums[i]
else:
sum += nums[i]
if sum > max:
max = sum
if sum <= 0:
sum = 0
i += 1
return max
执行结果
执行结果 : 通过
执行用时 : 40 ms, 在所有 Python3 提交中击败了98.80%的用户
内存消耗 : 13.9 MB, 在所有 Python3 提交中击败了36.33%的用户
复杂度分析
-
时间复杂度:O(n),
我们只遍历了包含有 n 个元素的列表一次。 -
空间复杂度:O(1),
所需的额外空间为常数级。
贪心算法
算法实现
class Solution:
def maxSubArray(self, nums: 'List[int]') -> 'int':
n = len(nums)
curr_sum = max_sum = nums[0]
for i in range(1, n):
curr_sum = max(nums[i], curr_sum + nums[i])
max_sum = max(max_sum, curr_sum)
return max_sum
执行结果
复杂度分析
-
时间复杂度:O(n),
我们只遍历了包含有 n 个元素的列表一次。 -
空间复杂度:O(1),
所需的额外空间为常数级。
动态规划(Kadane 算法)
算法实现
class Solution:
def maxSubArray(self, nums: 'List[int]') -> 'int':
n = len(nums)
max_sum = nums[0]
for i in range(1, n):
if nums[i - 1] > 0:
nums[i] += nums[i - 1]
max_sum = max(nums[i], max_sum)
return max_sum
执行结果
复杂度分析
-
时间复杂度:O(n),
我们只遍历了包含有 n 个元素的列表一次。 -
空间复杂度:O(1),
所需的额外空间为常数级。
分治法
算法实现
class Solution:
def cross_sum(self, nums, left, right, p):
if left == right:
return nums[left]
left_subsum = float('-inf')
curr_sum = 0
for i in range(p, left - 1, -1):
curr_sum += nums[i]
left_subsum = max(left_subsum, curr_sum)
right_subsum = float('-inf')
curr_sum = 0
for i in range(p + 1, right + 1):
curr_sum += nums[i]
right_subsum = max(right_subsum, curr_sum)
return left_subsum + right_subsum
def helper(self, nums, left, right):
if left == right:
return nums[left]
p = (left + right) // 2
left_sum = self.helper(nums, left, p)
right_sum = self.helper(nums, p + 1, right)
cross_sum = self.cross_sum(nums, left, right, p)
return max(left_sum, right_sum, cross_sum)
def maxSubArray(self, nums: 'List[int]') -> 'int':
return self.helper(nums, 0, len(nums) - 1)
执行结果
复杂度分析
-
时间复杂度:O(N logN)。
我们只遍历了包含有 n 个元素的列表一次。 -
空间复杂度:O(logN),
递归时栈使用的空间。
小结
先按照自己的想法设计,根据当前数字是否大于零以及当前和的情况,来确定是否要累加到当前和上,然后再判断并修改最大和。该思路与分治法很相似,之后学习了分治法,动态规划以及贪心算法的解决方法。