文章目录
题目
标题和出处
标题:分发饼干
出处:455. 分发饼干
难度
3 级
题目描述
要求
假设你是一位很棒的家长,想要给你的孩子们一些饼干。但是,你应该给每个孩子最多一块饼干。
每个孩子 i \texttt{i} i 都有一个胃口值 gi \texttt{gi} gi,这是能让孩子们满足胃口的饼干的最小尺寸;每块饼干 j \texttt{j} j 都有一个尺寸 sj \texttt{sj} sj。如果 sj ≥ gi \texttt{sj} \ge \texttt{gi} sj≥gi,则可以将饼干 j \texttt{j} j 分配给孩子 i \texttt{i} i,孩子 i \texttt{i} i 会得到满足。你的目标是满足最多数量的孩子,并返回这个最大值。
示例
示例 1:
输入: g = 1,2,3, s = 1,1 \texttt{g = 1,2,3, s = 1,1} g = 1,2,3, s = 1,1
输出: 1 \texttt{1} 1
解释:你有 3 \texttt{3} 3 个孩子和 2 \texttt{2} 2 块饼干, 3 \texttt{3} 3 个孩子的胃口值分别是 1 \texttt{1} 1、 2 \texttt{2} 2、 3 \texttt{3} 3。
虽然你有 2 \texttt{2} 2 块饼干,但是由于它们的尺寸都是 1 \texttt{1} 1,你只能让胃口值是 1 \texttt{1} 1 的孩子满足。
所以答案是 1 \texttt{1} 1。
示例 2:
输入: g = 1,2, s = 1,2,3 \texttt{g = 1,2, s = 1,2,3} g = 1,2, s = 1,2,3
输出: 2 \texttt{2} 2
解释:你有 2 \texttt{2} 2 个孩子和 3 \texttt{3} 3 块饼干, 2 \texttt{2} 2 个孩子的胃口值分别是 1 \texttt{1} 1、 2 \texttt{2} 2。
你有 3 \texttt{3} 3 块饼干,它们的尺寸可以让所有孩子满足。
所以答案是 2 \texttt{2} 2。
数据范围
- 1 ≤ g.length ≤ 3 × 10 4 \texttt{1} \le \texttt{g.length} \le \texttt{3} \times \texttt{10}^\texttt{4} 1≤g.length≤3×104
- 0 ≤ s.length ≤ 3 × 10 4 \texttt{0} \le \texttt{s.length} \le \texttt{3} \times \texttt{10}^\texttt{4} 0≤s.length≤3×104
- 1 ≤ gi, sj ≤ 2 31 − 1 \texttt{1} \le \texttt{gi, sj} \le \texttt{2}^\texttt{31} - \texttt{1} 1≤gi, sj≤231−1
解法
思路和算法
为了使最多数量的孩子得到满足,根据贪心思想,应按照孩子的胃口递增的顺序依次满足每个孩子,对于每个孩子,选择剩余饼干中能满足该孩子的最小尺寸的饼干,理由如下。
将数组 g g g 按升序排序之后,假设存在两个相邻孩子的胃口分别是 g 1 g_1 g1 和 g 2 g_2 g2,其中 g 1 ≤ g 2 g_1 \le g_2 g1≤g2,满足这两个孩子的最小尺寸的饼干的尺寸分别是 s 1 s_1 s1 和 s 2 s_2 s2,则必有 s 1 ≤ s 2 s_1 \le s_2 s1≤s2。当满足的孩子最多时,应将 s 1 s_1 s1 给 g 1 g_1 g1,将 s 2 s_2 s2 给 g 2 g_2 g2。假设给 g 1 g_1 g1 的饼干尺寸是 s 3 s_3 s3 且 s 3 > s 1 s_3 > s_1 s3>s1,考虑以下两种情况。
-
当 s 3 < s 2 s_3 < s_2 s3<s2 时,仍可以将 s 2 s_2 s2 给 g 2 g_2 g2,其余胃口更大的孩子的可用饼干数量不变,可以满足的孩子数量不变。
-
当 s 3 ≥ s 2 s_3 \ge s_2 s3≥s2 时,其余胃口更大的孩子的可用饼干数量不变或减少一块,因此可以满足的孩子数量不变或减少,不可能满足更多的孩子。
因此,对于每个孩子选择剩余饼干中能满足该孩子的最小尺寸的饼干,该贪心策略可以使最多数量的孩子得到满足。
具体做法是,首先将数组 g g g 和 s s s 按升序排序,然后使用双指针遍历两个数组,对于每个 g i gi gi,找到未使用的饼干下标中满足 s j ≥ g i sj \ge gi sj≥gi 的最小下标 j j j,则 s j sj sj 可以满足 g i gi gi。由于数组 g g g 和 s s s 已经按升序排序,因此遍历数组 g g g 的顺序为孩子的胃口递增顺序,可以满足孩子的饼干的最小尺寸也是递增的,和遍历数组 s s s 的顺序相同,只要遍历两个数组各一次即可得到可以满足的孩子的最多数量。
代码
java
class Solution {
public int findContentChildren(int[] g, int[] s) {
int count = 0;
Arrays.sort(g);
Arrays.sort(s);
int numOfChildren = g.length, numOfCookies = s.length;
int childIndex = 0, cookieIndex = 0;
while (childIndex < numOfChildren && cookieIndex < numOfCookies) {
if (g[childIndex] <= s[cookieIndex]) {
count++;
childIndex++;
}
cookieIndex++;
}
return count;
}
}
复杂度分析
-
时间复杂度: O ( m log m + n log n ) O(m \log m + n \log n) O(mlogm+nlogn),其中 m m m 和 n n n 分别是数组 g g g 和 s s s 的长度。两个数组排序分别需要 O ( m log m ) O(m \log m) O(mlogm) 和 O ( n log n ) O(n \log n) O(nlogn) 的时间,排序之后使用双指针遍历两个数组需要 O ( m + n ) O(m + n) O(m+n) 的时间,因此时间复杂度是 O ( m log m + n log n + m + n ) = O ( m log m + n log n ) O(m \log m + n \log n + m + n) = O(m \log m + n \log n) O(mlogm+nlogn+m+n)=O(mlogm+nlogn)。
-
空间复杂度: O ( log m + log n ) O(\log m + \log n) O(logm+logn),其中 m m m 和 n n n 分别是数组 g g g 和 s s s 的长度。两个数组排序分别需要 O ( log m ) O(\log m) O(logm) 和 O ( log n ) O(\log n) O(logn) 的递归调用栈空间。