LeetCode 455. 分发饼干
摘要
LeetCode 455 分发饼干题解,采用贪心策略,将饼干和孩子按胃口升序排列,用最小满足胃口的饼干去喂饱孩子,时间复杂度 O(n log n + m log m),空间复杂度 O(1)。
标签
#算法 #LeetCode #贪心 #双指针 #排序 #题解
目录
- 题目描述
- 易错点
- 思路
- 编写代码
1. 题目描述
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。
对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j]。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
示例 1:
text
输入: g = [1,2,3], s = [1,1]
输出: 1
解释: 你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。
虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。
所以你应该输出1。
示例 2:
text
输入: g = [1,2], s = [1,2,3]
输出: 2
解释: 你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。
你拥有的饼干数量和尺寸都足以让所有孩子满足。
所以你应该输出2。
提示:
1 <= g.length <= 3 * 10^40 <= s.length <= 3 * 10^41 <= g[i], s[j] <= 2^31 - 1
2. 易错点
- 饼干或孩子数组可能为空:若任一数组为空,直接返回 0(代码中
while条件自动处理)。 - 排序的必要性:为了使用双指针贪心,必须先将两个数组升序排列。
- 双指针移动逻辑:满足胃口时,孩子指针
i和饼干指针j都前进;不满足时,只有饼干指针j前进(尝试更大的饼干)。 - 贪心策略:优先用最小的饼干去满足胃口最小的孩子,才能最大化满足数量。
- 返回值:
i即为最终满足的孩子数量(因为i从 0 开始递增)。
3. 思路
本题采用贪心算法,核心思想是“局部最优达到全局最优”:为了满足尽可能多的孩子,应该优先用尺寸最小的饼干去喂胃口最小的孩子。如果当前最小的饼干都满足不了当前胃口最小的孩子,那么这块饼干对任何孩子都无效(因为其他孩子胃口更大),直接丢弃;如果当前最小饼干能满足当前最小胃口,则分配给他们,然后继续匹配下一对。
排序:先将两个数组升序排列,这样双指针从小到大依次比较。
双指针遍历:
i指向当前待满足的孩子(胃口值g[i])。j指向当前待分配的饼干(尺寸s[j])。- 若
s[j] >= g[i],则分配成功,i++(下一个孩子),j++(下一块饼干)。 - 否则,
j++(跳过这块饼干,尝试更大的尺寸)。 - 当任一指针超出范围时,遍历结束,返回
i(已满足的孩子数量)。
为什么贪心有效?
因为孩子按胃口升序,饼干按尺寸升序。如果当前最小饼干都不能满足当前最小胃口,那么它一定不能满足任何孩子,丢弃它是最优的;如果能满足,分配给当前最小胃口的孩子不会让结果变差(因为更大的饼干可以留给胃口更大的孩子)。这是典型的“双指针贪心”应用。
时间复杂度 O(n log n + m log m)(排序),空间复杂度 O(1)(不计排序栈空间)。
4. 编写代码
javascript 运行
javascript
var findContentChildren = function(g, s) {
g.sort((a, b) => a - b);
s.sort((a, b) => a - b);
let i = 0, j = 0;
while (i < g.length && j < s.length) {
if (s[j] >= g[i]) i++;
j++;
}
return i;
};