一、前置核心知识点:贪心算法
1. 贪心算法定义
在每一步做出当前最优选择,从而希望得到全局最优解。核心思想是:局部最优 → 全局最优。
2. 适用场景
问题可分解为若干子问题,且每个子问题的最优解能组合成全局最优解。
3. 贪心算法步骤
- 将问题分解为若干子问题
- 找出适合的贪心策略
- 求解每一个子问题的最优解
- 将局部最优解堆叠成全局最优解
二、经典算法题:最大子数组和(LeetCode 53)
题目描述
给你一个整数数组 nums,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
- 输入:
nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4] - 输出:
6 - 解释:连续子数组
[4, -1, 2, 1]的和最大,为6。
最优解法:贪心算法
核心思路
遍历数组时,维护当前连续子数组和:
- 如果当前累计和
current_sum < 0,说明它对后续元素是 “拖累”,直接抛弃之前的子数组,从当前元素重新开始累计。 - 如果当前累计和
> 0,则继续累加。 - 同时维护一个
max_sum记录遍历过程中出现的最大和。
代码实现
from typing import List
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
if not nums:
return 0
current_sum = 0
max_sum = nums[0] # 初始化为第一个元素,避免全负数场景
for num in nums:
# 如果当前累计和为负,重置为0,从当前元素重新开始
if current_sum < 0:
current_sum = 0
current_sum += num
# 更新最大和
if current_sum > max_sum:
max_sum = current_sum
return max_sum
三、关键逻辑详解
1. 核心判断
if current_sum < 0: current_sum = 0
- 当之前的累计和为负数时,它会拉低后续元素的和,因此抛弃它,从当前元素重新开始更优。
- 例如:
[-2, 1]中,-2是拖累,直接重置为0,再+1得到1,比-2+1=-1更大。
2. 边界处理
- 初始化
max_sum = nums[0],避免数组全为负数时返回0。 - 例如:
nums = [-1, -2, -3],最大子数组和为-1。
3. 复杂度分析
- 时间复杂度:O (n),仅遍历一次数组。
- 空间复杂度:O (1),仅使用常数额外空间。
四、算法对比与拓展
1. 与动态规划对比
- 贪心解法:O (n) 时间 + O (1) 空间,更高效。
- 动态规划:
dp[i] = max(nums[i], dp[i-1]+nums[i]),思路类似但空间复杂度稍高。
2. 拓展场景
- 求最小子数组和:将贪心逻辑反转,维护最小和。
- 求最长连续子数组:在贪心基础上记录子数组起止索引。