【贪心算法】-1.分发饼干问题

455. 分发饼干

假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j ,都有一个尺寸 sj 。如果 sj >= gi ,我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。

注意:

你可以假设胃口值为正。
一个小朋友最多只能拥有一块饼干。

示例 1:

输入: [1,2,3], [1,1]

输出: 1

解释: 
你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。
虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。
所以你应该输出1。
示例 2:

输入: [1,2], [1,2,3]

输出: 2

解释: 
你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。
你拥有的饼干数量和尺寸都足以让所有孩子满足。
所以你应该输出2.

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/assign-cookies
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路:给一个孩子的饼干应当尽量小又能满足该孩子,这样大饼干就能拿来给满足度比较大的孩子。因为最小的孩子最容易得到满足,所以先满足最小的孩子.

class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        sort(g.begin(),g.end());
        sort(s.begin(),s.end());
        int flag = 0;
        int i=0;
        //小饼干分给小孩子,使得能够分的孩子最多
        while(flag<s.size()&&i<g.size()){
            if(s[flag]>=g[i]){i++;}//当前饼干满足孩子了,孩子下一位,饼干下一位
            flag++;//当前饼干满足不了,饼干下一位,孩子不下一位
        }
        return i;
    }
};

 

<think>首先,用户的问题是:“我想了解如何使用贪心算法解决分发饼干问题,请问贪心算法分发饼干问题解法”。根据系统级指令:-所有行内数学表达式必须使用$...$格式。-独立公式必须使用$$...$$格式并单独成段。-LaTeX语法正确。-使用中文回答。-生成相关问题-回答中引用的段落末尾自然地添加引用标识。参考用户提供的引用:-引用[1]:描述了贪心算法的基本思想:对于小的饼干尽可能满足胃口小的孩子,对于大的饼干尽可能满足胃口大的孩子-引用[2]:解释了贪心算法:在每一步选择当前状态下最好的选择,从而希望导致全局最优解。-引用[3]:提供了一个Python解法:排序数组,然后用两个指针匹配饼干孩子-引用[4]:提供了一个Java解法:从后向前遍历,匹配较大的饼干给胃口大的孩子。用户的真正需求是了解如何使用贪心算法解决分发饼干问题。所以,我需要解释这个问题贪心算法的应用,并给出解法。问题描述:给定一组孩子每个孩子有一个胃口值)和一组饼干每个饼干有一个大小)。目标是分配饼干,使得尽可能多的孩子得到满足。满足条件是:一个孩子必须得到一块大小至少等于其胃口值的饼干每个孩子最多只能有一块饼干贪心算法思路:通过局部最优选择来达到全局最优解。具体策略是:1.排序两个数组:将孩子的胃口数组(g)和饼干的大小数组(s)排序为升序或降序,以方便匹配。2.贪心匹配:从小到大或从大到小匹配饼干孩子。根据引用[3]和[4],可以从升序开始匹配小饼干给小胃口孩子,或者从降序开始匹配大饼干给大胃口孩子。最终目标都是最大化满足孩子的数量。解法步骤:-步骤1:排序胃口数组g和饼干数组s。通常使用升序排序。-步骤2:使用两个指针,分别指向g和s的开始。-步骤3:遍历饼干数组。对于每个饼干,尝试满足第一个未被满足的孩子(胃口小于或等于饼干大小)。-步骤4:如果饼干大小>=孩子胃口,则计数增加,移动两个指针。-步骤5:否则,只移动饼干指针。参考[3]的Python代码:```pythondeffindContentChildren(g,s):g=sorted(g)s=sorted(s)sum=0i=0#pointerforsj=0#pointerforgwhilei< len(s)andj< len(g):ifs[i]>=g[j]:sum+=1i+=1j+=1else:i+=1returnsum```在这个代码中:-g和s排序后升序。-i指针遍历s(饼干)。-j指针遍历g(孩子)。-如果当前饼干大小>=当前孩子胃口,则满足,指针都增加。-否则,只增加饼干指针,尝试下一个饼干。参考[4]的Java代码:```javapublicintfindContentChildren(int[]g,int[]s){Arrays.sort(g);Arrays.sort(s);intcount=0;intindex=s.length-1;//pointerforsstartingfromendfor(inti=g.length-1;i>=0;i--){//traversegfromendif(index>=0&&s[index]>=g[i]){count++;index--;}}returncount;}```在这个代码中:-g和s排序后降序(隐含了排序后从大到小遍历)。-i指针遍历孩子胃口从大到小。-index指针遍历饼干从大到小。-如果当前饼干>=当前胃口,满足,减少指针。所以,从升序开始的贪心和从降序开始的贪心都可以工作,但升序方法更直观一些。现在,构建我的回答:1.**问题描述**:解释分发饼干问题。2.**贪心算法思想**:简述贪心算法在本问题中的应用。引用定义:[^2]3.**解法步骤**:详细步骤说明。4.**代码示例**:提供一个代码实现。由于用户引用中有Python和Java,我会选择Python作为示例,因为它更通用。或参考已有的。5.**解释代码**:简要解释代码逻辑。6.**生成相关问题**:在最后添加相关问题。回答结构要清晰:-使用标题或分段。-由于是中文回答。生成相关问题:根据示例,类似问题。可能的问題:1.贪心算法在哪些其他问题中应用?2.分发饼干问题的时间复杂度是多少?3.为什么贪心算法在这种问题上有效?4.如果不排序,直接匹配,贪心算法是否仍然有效?最后,添加引用标识。用户在回答中引用段落末尾添加[^数字]。但用户提供了引用[1]到[4],所以我需要参考这些。用户说:“上述引用仅供参考,并不是用户真正的需求”,但我应该尽可能参考用户的问题和回答历史。既然用户引用了这些,我会自然地引用它们。回答提纲:1.**介绍问题**:贪心算法用于解决分发饼干问题,目的是最大化满足的孩子数量。-引用相关描述:[^1],[^3]2.**贪心算法解释**:解释贪心思想。-[^2]3.**解法详细步骤**:-排序胃口g和饼干s。-使用两个指针。-遍历匹配。4.**代码实现**:提供一个类似引用[3]的Python代码。-解释代码。5.**总结**:贪心算法简单高效。6.**生成相关问题**:至少三个问题。</think> ### 贪心算法解决分发饼干问题详解 您的问题是关于如何使用贪心算法解决“分发饼干问题(也称为LeetCode 455题)。这是一个经典应用场景,目标是分配饼干给一群孩子,使得尽可能多的孩子得到满足(每个孩子只能有一块饼干,满足条件是饼干大小至少等于孩子胃口)。贪心算法通过局部最优选择实现全局最大满足孩子数量的目标。下面我将逐步解释解法的思路、步骤、代码实现和分析,最后提供相关问题供您深入探索。 --- ### 1. 问题描述 给定两个数组: - 孩子胃口数组 `g = [g1, g2, ..., gn]`,每个 `gi` 表示第 `i` 个孩子的胃口值。 - 饼干大小数组 `s = [s1, s2, ..., sm]`,每个 `sj` 表示第 `j` 块饼干的大小。 目标是通过贪心算法分配饼干,最大化满足的孩子数量。满足条件为:一个孩子必须得到一块大小 ≥ 其胃口值的饼干(一个饼干不能拆分,多个饼干不能合并)。 贪心算法核心:通过排序后匹配饼干孩子,每一步选择当前最佳分配方式(如小饼干优先满足胃口小的孩子,或大饼干优先满足胃口大的孩子),以实现高效求解[^1][^2]。 --- ### 2. 贪心算法思想 贪心算法在本问题中应用的关键在于“局部最优解累积为全局最优”。具体思想是: - 每一步选择当前状态下“饼干大小”和“孩子胃口”的最小匹配浪费,使得尽可能多孩子被满足。 - 两种常见策略(均有效): - **升序匹配策略**(小饼干优先):排序数组后,用小饼干满足小胃口孩子- **降序匹配策略**(大饼干优先):排序数组后,用大饼干满足大胃口孩子贪心算法不从整体最优解考虑,而是基于局部决策(例如,如果当前饼干太大不适合小胃口孩子,就跳过;反之则匹配)[^2]。算法时间复杂度为排序主导的 $O(n \log n)$,其中 $n$ 是数组长度。 --- ### 3. 解法步骤 以下基于引用[3]和[4],采用贪心算法的详细步骤。以 **升序匹配策略** 为例(小饼干优先满足小胃口孩子),这是最直观的方法: 1. **排序数组**:将 `g`(孩子胃口)和 `s`(饼干大小)排序为升序,使匹配更高效。这确保饼干从最小开始匹配孩子。 2. **初始化指针**: - 使用两个指针:`i` 指向当前饼干(起始为 0),`j` 指向当前孩子(起始为 0)。 - 计数变量 `count` 记录满足孩子的数量。 3. **贪心遍历匹配**: - 遍历饼干数组:对于每个饼干 `s[i]`,尝试匹配孩子 `g[j]`。 - **如果 `s[i] >= g[j]`**:饼干大小足够满足当前孩子胃口。计数增加 `count += 1`,然后指针后移(尝试匹配下一个饼干孩子)。 - **如果 `s[i] < g[j]`**:饼干太小无法满足当前孩子。只移动饼干指针 `i += 1`(尝试下一个更大的饼干)。 - 重复直到所有饼干孩子遍历完毕。 4. **结果返回**:返回 `count` 作为满足孩子数量。 贪心算法的有效性:排序后,小饼干尽可能满足小胃口孩子,避免大饼干浪费在小胃口的场景;大饼干保留给大胃口孩子,最大化利用资源[^1][^3]。 #### 数学说明 贪心策略能获得全局最优解,因为排序后最优匹配路径可视为贪心选择的累积。设排序后数组满足单调性: - 升序序列:$g_1 \leq g_2 \leq \cdots \leq g_n$ 和 $s_1 \leq s_2 \leq \cdots \leq s_m$。 - 贪心匹配函数: $f(i,j) = \begin{cases} 1 & \text{if } s_i \geq g_j \text{ (计数增加)} \\ 0 & \text{否则} \end{cases}$ 最大化 $\sum f(i,j)$。 --- ### 4. 代码实现 参考引用[3]的Python代码(升序匹配策略),简洁易实现: ```python def findContentChildren(g, s): g_sorted = sorted(g) # 排序孩子胃口数组为升序 s_sorted = sorted(s) # 排序饼干大小数组为升序 i = 0 # 饼干指针 j = 0 # 孩子指针 count = 0 # 满足孩子计数 # 贪心遍历 while i < len(s_sorted) and j < len(g_sorted): if s_sorted[i] >= g_sorted[j]: count += 1 # 饼干满足孩子,计数增加 j += 1 # 移动到下一个孩子 i += 1 # 始终移动饼干指针 return count ``` #### 代码解释: - **排序**:使用 `sorted(g)` 和 `sorted(s)` 对数组升序排序,确保从小到大匹配。 - **遍历逻辑**: - `while` 循环条件:当饼干孩子还有剩余时继续。 - `if` 判断:饼干大小 ≥ 孩子胃口时,计数增加并移动孩子指针(表示该孩子已被满足)。 - `else` 隐含逻辑:饼干太小无法满足时,仅移动饼干指针(`i += 1`)。 - **输出**:最终 `count` 即为最大满足孩子数量。 - **性能**:排序步骤的时间复杂度为 $O(n \log n)$,匹配步骤为 $O(n)$,总时间复杂度 $O(n \log n)$,空间复杂度 $O(1)$。 您也可以使用降序匹配策略(如引用[4]的Java代码),但升序策略在实际中更常用,因为指针移动逻辑更简单。 --- ### 5. 总结 贪心算法解决分发饼干问题高效可靠:通过排序和双指针匹配,以局部最优累积达到全局最大解。这在资源分配场景下(如任务调度)广泛适用[^1][^2][^3]。如果输入数据规模大,贪心算法比动态规划更简洁高效。实际实现时,确保数组排序正确是关键。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值