题目描述

✅ 455. 分发饼干

image-20260928224150782

image-20260928224150783

题意分析

每个孩子有一个胃口值,每块饼干有一个尺寸。只有饼干尺寸不小于孩子的胃口,这个孩子才得到满足;每个孩子最多获得一块饼干,每块饼干也只能使用一次。返回最多能满足多少个孩子,不需要给出具体分配方案。

不能把多块小饼干合并给一个孩子,也不需要让所有孩子都得到饼干。相同胃口或相同尺寸仍对应不同的孩子、不同的饼干,都按出现次数参与分配;饼干数组允许为空。

解法:排序 + 双指针

核心思路

[!blue]

将胃口和饼干尺寸都升序排序。用 i 指向尚未满足的最小胃口,用 j 指向尚未处理的最小饼干。优先给最容易满足的孩子寻找最小可行饼干,把更大的饼干留给后面要求更高的孩子。

若 s[j] < g[i],这块饼干连最小的剩余胃口都满足不了,更不可能满足后面的孩子,因此可以直接舍弃,只推进饼干指针。当前孩子仍可能被后续更大的饼干满足,不能一起跳过。

若 s[j] >= g[i],就把这块饼干分给当前孩子。这个选择不会减少最优人数:若某个最优方案给当前孩子用了更大饼干,可以交换成这块最小可行饼干,换出的较大饼干仍能承担原来这块饼干的任务;若最优方案没有满足当前孩子,把这块饼干改给他,也不会减少已经满足的总人数。

因此每次成功匹配都可以保留在某个最优方案中,剩余部分仍是同样的问题。成功时两指针一起前进并计数,失败时只推进饼干指针。孩子或饼干任意一侧耗尽后,再也无法增加匹配数量,直接结束。

代码使用原地排序,会改变两个输入数组的顺序。排序只是为了确定安全的贪心次序,并不改变每个孩子和每块饼干只能使用一次的限制。

解题步骤

  1. 将胃口数组 g 和饼干数组 s 分别升序排序。
  2. 初始化两个指针和满足人数为零。
  3. 当前饼干足够大时,满足当前孩子,人数加一并同时推进两侧。
  4. 当前饼干太小时,只推进饼干指针。
  5. 任一指针到末尾时返回已满足人数。

代码实现

class Solution {
    // 排序后优先用最小可行饼干满足胃口最小的孩子,不会影响后续更大胃口的孩子。
    public int findContentChildren(int[] g, int[] s) {
        Arrays.sort(g);
        Arrays.sort(s);

        int i = 0;
        int j = 0;
        int count = 0;

        while (i < g.length && j < s.length) {
            if (s[j] >= g[i]) {
                // 最小可行饼干满足当前最小胃口,两侧同时前进
                count++;
                i++;
                j++;
            } else {
                // 饼干太小,只跳过饼干,当前孩子仍可由后续饼干满足
                j++;
            }
        }

        return count;
    }
}
import "sort"

func findContentChildren(g []int, s []int) int {
    // 排序后优先用最小可行饼干满足胃口最小的孩子,不会影响后续更大胃口的孩子。
    sort.Ints(g)
    sort.Ints(s)

    i, j := 0, 0
    count := 0

    for i < len(g) && j < len(s) {
        if s[j] >= g[i] {
            // 最小可行饼干满足当前最小胃口,两侧同时前进
            count++
            i++
            j++
        } else {
            // 饼干太小,只跳过饼干,当前孩子仍可由后续饼干满足
            j++
        }
    }

    return count
}

复杂度分析

  • 时间复杂度:$O(n\log(n + 1) + m\log(m + 1))$,n 为孩子数,m 为饼干数。排序后的双指针扫描为 $O(n + m)$。
  • 空间复杂度:扫描部分为 $O(1)$;整体还需计入 Java、Go 标准库排序实现使用的辅助空间,不能因为扫描未建新数组就将总空间一概视为常数。

关键点总结

[!green]

  • 最小可行饼干满足最小剩余胃口,可以通过交换论证保留最优人数。
  • 太小的饼干对所有剩余孩子都无用,可以舍弃;孩子本身仍需等待。
  • 两指针之前的对象都已处理,匹配后同步推进保证不会重复使用。

易错点总结

[!yellow]

  • 未排序就按当前次序分配,可能先用掉较大的饼干,让后面的更大胃口无法满足。
  • 饼干太小时同时推进孩子,会漏掉仍可由后续饼干满足的人。
  • 比较条件写成严格大于,会拒绝尺寸刚好等于胃口的有效匹配。
  • 将多个饼干尺寸相加后匹配一个孩子,改变了每人最多一块的题目规则。
  • 忽略排序对输入顺序的修改,误以为函数仅仅读取原数组。

相似题目

题目 难度 关联与区别
870. 优势洗牌 中等 同样匹配两组大小需求,本题让最小足够饼干满足最小胃口,原题还需把无法获胜的值分配给对方。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2026/23924940
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!