《贪心算法:5 个实战案例(附 LeetCode 题解)》
·
贪心算法:5 个实战案例(附 LeetCode 题解)
贪心算法在每一步选择中都采取当前状态下最优的决策,最终得到全局最优解。以下是 5 个经典案例,均附 Python 实现和 LeetCode 题解。
案例 1:分发饼干(LeetCode 455)
问题描述
给定孩子胃口值数组 $g$ 和饼干尺寸数组 $s$,每个孩子最多分得一块饼干。若 $s_j \geq g_i$,则饼干 $j$ 可满足孩子 $i$。求最多可满足的孩子数。
贪心策略
- 优先满足胃口最小的孩子
- 使用能满足该孩子的最小饼干
数学表达:
$$ \text{max} \sum_{i=1}^{n} \mathbf{1}_{s_j \geq g_i} \quad \text{s.t.} \quad j \text{ 未被使用} $$
def findContentChildren(g, s):
g.sort()
s.sort()
child = cookie = 0
while child < len(g) and cookie < len(s):
if s[cookie] >= g[child]:
child += 1
cookie += 1
return child
复杂度
- 时间:$O(n \log n + m \log m)$(排序开销)
- 空间:$O(1)$
题解链接:LeetCode 455
案例 2:无重叠区间(LeetCode 435)
问题描述
给定区间数组 intervals = [[start_i, end_i]],求最少移除多少区间可使剩余区间互不重叠。
贪心策略
- 按结束时间升序排序
- 优先保留结束早的区间,减少后续重叠
数学表达:
$$ \text{min} \left( n - \max_{\text{非重叠}} |S| \right) $$
def eraseOverlapIntervals(intervals):
intervals.sort(key=lambda x: x[1])
end = float('-inf')
count = 0
for s, e in intervals:
if s >= end:
end = e
else:
count += 1
return count
复杂度
- 时间:$O(n \log n)$
- 空间:$O(1)$
题解链接:LeetCode 435
案例 3:买卖股票 II(LeetCode 122)
问题描述
给定股价数组 prices,可多次买卖(卖后方可再买),求最大利润。
贪心策略
- 所有上涨日都买卖:若 $p_i > p_{i-1}$,则利润累加 $p_i - p_{i-1}$
数学表达:
$$ \text{profit} = \sum_{i=1}^{n} \max(p_i - p_{i-1}, 0) $$
def maxProfit(prices):
profit = 0
for i in range(1, len(prices)):
if prices[i] > prices[i-1]:
profit += prices[i] - prices[i-1]
return profit
复杂度
- 时间:$O(n)$
- 空间:$O(1)$
题解链接:LeetCode 122
案例 4:跳跃游戏(LeetCode 55)
问题描述
给定数组 nums,初始位置在索引 0,$nums_i$ 表示从 $i$ 可跳跃的最大长度。判断能否到达最后一个索引。
贪心策略
- 维护当前能到达的最远位置
max_reach - 若 $i > \text{max_reach}$ 则失败
数学表达:
$$ \text{max_reach} = \max_{k \leq i} (k + \text{nums}_k) $$
def canJump(nums):
max_reach = 0
for i in range(len(nums)):
if i > max_reach:
return False
max_reach = max(max_reach, i + nums[i])
return True
复杂度
- 时间:$O(n)$
- 空间:$O(1)$
题解链接:LeetCode 55
案例 5:划分字母区间(LeetCode 763)
问题描述
给定字符串 s,将其划分为尽可能多的片段,使得同一字母最多出现在一个片段中。
贪心策略
- 记录每个字母最后出现的位置
- 遍历时更新当前片段的边界
end = \max(\text{end}, \text{last}_c) - 当 $i = \text{end}$ 时分割片段
def partitionLabels(s):
last = {c: i for i, c in enumerate(s)}
start = end = 0
res = []
for i, c in enumerate(s):
end = max(end, last[c])
if i == end:
res.append(end - start + 1)
start = i + 1
return res
复杂度
- 时间:$O(n)$
- 空间:$O(1)$(字母表大小固定)
题解链接:LeetCode 763
贪心算法核心要点
- 适用场景:问题具有最优子结构,且局部最优能导向全局最优
- 证明关键:需证明贪心选择的安全性(如交换论证、数学归纳法)
- 典型问题特征:区间调度、背包变种、路径覆盖、分配问题等
以上代码均通过对应 LeetCode 测试用例,可直接提交验证。
更多推荐


所有评论(0)