题目:
给定一个整数数组 nums
,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和
如果你已经实现复杂度为 O(n)
的解法,尝试使用更为精妙的 分治法 求解
题目链接:最大自序和
题目限制:
时间复杂度为O(n)
解题思路:
子序和由连续数组组成
子数组最少包含一个元素
数组边界:
当数组元素全为整数时,数组和即为最大子序和
当数组元素全为负数时,数组元素最大值即为最大子序和
当数组同时存在正负数时,最大子序和的连续数组必定以正数开始
当最大子序和小于数组元素最大值时,数组元素最大值即为最大子序和
实现代码:
测试数组nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
通过测试结果[4, -1, 2, 1],反推编码执行过程
贪心法
# 贪心法
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
sum, result = 0, float("-inf") # float('-inf') 正负无穷的意思
for i in range(len(nums)): # 遍历nums
sum += nums[i] # 数组元素相加
result = max(result, sum) # 取最大值
if (sum < 0): # 丢弃小于0的子序和
sum = 0
return result
贪心法的核心逻辑:若当前指针所指元素之前的和小于0,则丢弃当前元素之前的数列
一边遍历,一边计算子序和,当子序和相加为负数时,丢弃该子序和
截取官方视频解说的片段
由解题思路可知, 最大子序和需正数开始,通过一边遍历,一边对比当前和和最大和的值
动态规划
# 动态规划
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
for i in range(1, len(nums)): # 由return 返回结构可知,当数组元素只有一个时,无需对比
if nums[i - 1] > 0: # 最大子序和条件
nums[i] += nums[i - 1] # 计算该组子序和
return max(nums) # 取最大的子序和
动态规划的核心逻辑:若前一个元素大于0,则将其加到当前元素上
一边遍历,一边计算正数开始的子序和,最后返回最大的子序和
截取官方视频解说的片段
更简洁的方法
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
for i in range(1, len(nums)):
nums[i]= nums[i] + max(nums[i-1], 0)
return max(nums)
nums[i - 1] 是第 i - 1 个元素
max(nums[i - 1] ,0)是与0对比 i元素前最大的元素
该代码的运行逻辑和通过贪心法和动态规划的思路结合在一起
该代码的缺点就是会比动态规划运行得更慢,因为执行了两次max()函数
结论:
该题主要难点是考察是否可理清找到最大子序和的逻辑思路
max()内置函数的深入应用
动态规划的基础使用
LeetCode相关数组题:
【leecode】第35题:搜索插入位置_inganxu-CSDN博客