文章目录
- 摘要
- 描述
- 题解答案(核心思路)
- 贪心策略怎么定?
- 为什么这个策略是对的?
- 题解答案(Swift 可运行 Demo)
- 题解代码分析
- 1. 为什么一定要排序?
- 2. 双指针的意义
- 3. 关键判断逻辑
- 4. 为什么不会漏解?
- 示例测试及结果
- 示例 1
- 示例 2
- 自定义测试
- 实际场景结合
- 1. 资源分配问题
- 2. 人力与任务匹配
- 3. 面试中的信号题
- 时间复杂度
- 空间复杂度
- 总结
摘要
LeetCode 455 是一道非常经典的贪心入门题。
题目本身不复杂,但如果你第一次写,很容易陷入一种纠结:
- 是不是要给胃口最大的孩子最大的饼干?
- 要不要试所有组合?
- 会不会分配错了,后面没法满足更多孩子?
其实这道题的核心只有一句话:
用最小的资源,优先满足最容易满足的人。
一旦想通这一点,代码就会变得非常干净,而且效率也很高。
描述
你有两组数据:
g[i]:第i个孩子的胃口值(最小需要多大的饼干)s[j]:第j块饼干的尺寸
规则很简单:
- 一个孩子最多只能拿一块饼干
- 一块饼干只能给一个孩子
- 只有当
s[j] >= g[i],这个孩子才会满足
你的目标不是让所有孩子都满足,而是:
尽可能多地满足孩子,返回最大数量
题解答案(核心思路)
贪心策略怎么定?
这道题的贪心策略其实非常直觉化:
先排序
- 孩子的胃口从小到大排
- 饼干的尺寸从小到大排
用最小的饼干,去尝试满足胃口最小的孩子
如果当前饼干满足不了这个孩子,那它也一定满足不了胃口更大的孩子,直接丢弃
如果能满足,就计数 +1,同时换下一个孩子和下一块饼干
为什么这个策略是对的?
因为:
- 胃口小的孩子选择空间最大
- 小饼干是“最稀缺”的资源
- 如果你用大饼干去喂小胃口的孩子,很可能会浪费掉大饼干
这和现实生活其实一模一样。
题解答案(Swift 可运行 Demo)
classSolution{funcfindContentChildren(_g:[Int],_s:[Int])->Int{// 1. 排序letchildren=g.sorted()letcookies=s.sorted()varchildIndex=0varcookieIndex=0varresult=0// 2. 双指针遍历whilechildIndex<children.count&&cookieIndex<cookies.count{ifcookies[cookieIndex]>=children[childIndex]{// 当前饼干可以满足当前孩子result+=1childIndex+=1cookieIndex+=1}else{// 饼干太小,换一块更大的cookieIndex+=1}}returnresult}}题解代码分析
1. 为什么一定要排序?
letchildren=g.sorted()letcookies=s.sorted()排序之后有两个好处:
- 胃口小的孩子排在前面,优先满足
- 饼干尺寸从小到大,避免浪费大饼干
如果不排序,你就很难保证当前的分配是“最省资源”的。
2. 双指针的意义
varchildIndex=0varcookieIndex=0这两个指针分别表示:
childIndex:当前要尝试满足的孩子cookieIndex:当前拿来用的饼干
指针只往前走,不回退,这也是贪心算法的典型特征。
3. 关键判断逻辑
ifcookies[cookieIndex]>=children[childIndex]- 满足:说明这块饼干是“刚刚好或更大”,直接用
- 不满足:说明这块饼干太小,留着也没用,换下一块
这里有个非常重要但容易忽略的点:
如果当前饼干满足不了当前孩子,那它一定满足不了后面的孩子。
4. 为什么不会漏解?
因为:
- 每个孩子只会尝试一次
- 每块饼干只会使用或丢弃一次
- 没有回头路,但这是正确的回头路不需要走
示例测试及结果
示例 1
letsolution=Solution()print(solution.findContentChildren([1,2,3],[1,1]))输出:
1解释过程:
- 饼干:[1,1]
- 孩子胃口:[1,2,3]
- 只能满足胃口为 1 的孩子
示例 2
print(solution.findContentChildren([1,2],[1,2,3]))输出:
2解释过程:
- 饼干足够
- 每个孩子都能被满足
自定义测试
print(solution.findContentChildren([2,3,4],[1,2,3]))结果:
2解释:
- 胃口 2 用饼干 2
- 胃口 3 用饼干 3
- 胃口 4 无法满足
实际场景结合
这道题的思路在真实世界中非常常见。
1. 资源分配问题
- 带宽分配
- 内存分配
- 任务调度
本质都是:
用有限资源,尽量满足更多请求
2. 人力与任务匹配
比如:
- 初级任务给初级工程师
- 高难度任务留给高级工程师
如果你反过来分配,很容易“浪费能力”。
3. 面试中的信号题
这道题经常被用来考:
- 是否理解贪心的正确性
- 是否能写出简洁、不绕弯的代码
- 是否能解释为什么这样贪是对的
时间复杂度
- 排序:
O(n log n) - 双指针遍历:
O(n)
整体时间复杂度:
O(n log n)空间复杂度
- 排序需要额外空间(取决于语言实现)
- 指针变量是常量级
空间复杂度:
O(1)(忽略排序带来的额外空间)总结
LeetCode 455 是一道非常值得反复体会的贪心题:
- 思路简单
- 逻辑清晰
- 非常贴近真实世界的决策方式
如果你能把这道题讲清楚,说明你已经不只是“刷题”,而是在真正理解算法的决策逻辑。