通俗易懂贪心算法一:分配问题
Posted 比特的一天
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通俗易懂贪心算法一:分配问题相关的知识,希望对你有一定的参考价值。
看完本文,可以顺便解决leetcode以下两个题目:
455.分发饼干(简单)
135.分发糖果(困难)
一、通俗易懂的贪心算法 | 思想
贪心算法就是采用贪心的策略,保证每一次的操作都是局部最优的,从而使得结果是全局最优的。
比如,A、B、C、都很喜欢吃橘子,A可以吃5个、B可以吃3个、C可以吃1个;但是现在只有7个橘子,问最多几个人可以吃饱;
我们选用的贪心策略就是,吃的少的人先吃,尽量先使用量少的人吃饱,所以在这里,B、C肯定是可以吃饱的;
在这里,又因为全局结果是局部结果的简单求和,因此,局部最优的策略同样也是全局最优的策略。
二、分配问题
455.分发饼干(简单)
题目描述
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值
来源:力扣(LeetCode)
看描述很迷,其实说白了就是:有一群孩子和一堆饼干,每个孩子有自己的饥饿度,饼干也分大小程度,一个孩子只能吃一个饼干,而且这个饼干的大小要大于孩子的饥饿度;求解最多能有多少孩子可以吃饱?
输入输出样例
输入: g = [1,2,3], s = [1,1] 输出: 1 解释: 你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。所以你应该输出1。
来源:力扣(LeetCode)
题解
根据我们局部最优的思想,当然是饥饿度小的孩子先吃了,毕竟饼干只有这么多,但是同时应该尽量使得剩下的饼干大小能够满足后面的孩子去吃;
因此,我们应该在饼干大小 >= 这个孩子饥饿度的饼干中,寻找到最小的那个饼干去喂他;满足一个孩子吃饱之后,继续使用同样的方法去喂饱下一个孩子,知道不能满足条件为止;
简而言之就是,给饥饿度小的孩子分配满足条件的饼干中大小最小的饼干。
class Solution {
public:
int findContentChildren(vector<int>& g, vector<int>& s) {
//贪心算法 先排序 然后依次比较
sort(g.begin(),g.end()); //g 胃口 s 饼干大小
sort(s.begin(),s.end());
int i = 0,j = 0;
while(i < g.size() && j < s.size()) {
if(g[i] <= s[j]) {
i++;
}
j++;
}
return i;
}
};
135.分发糖果(困难)
题目描述
老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。你需要按照以下要求,帮助老师给这些孩子分发糖果:每个孩子至少分配到 1 个糖果。评分更高的孩子必须比他两侧的邻位孩子获得更多的糖果。那么这样下来,老师至少需要准备多少颗糖果呢?
来源:力扣(LeetCode)
我们继续来把题目描述的通俗一些:有评分属性的孩子,排成一排,每一个孩子至少有一个糖果,如果一个孩子比左右两个孩子评分高,则他的糖果肯定要比左右两位的高
输入输出样例
输入:[1,0,2]
输出:5
解释:你可以分别给这三个孩子分发 2、1、2 颗糖果。
题解
上述455题,我们首先对于数据进行了排序,这是数据处理的常规操作,为了方便后续的大小比较;
但是此题我们使用两次遍历;我们的贪心策略是:每一次遍历只考虑相邻一侧的关系;
1)每一个孩子的糖果初始化 1
2)从左到右遍历一次;如果右边孩子比左边孩子评分高,那么右边孩子得到的糖果比左边的多一个;
3)从右到左遍历一次;如果左边孩子比右边孩子评分高,而且当前左边孩子的糖果是比右边孩子糖果少,那么左边孩子得到的糖果比右边的多一个;
class Solution {
public:
int candy(vector<int>& ratings) {
int size = ratings.size();
if (size < 2) {
return size;
}
vector<int> num(size,1); // 先都给一个糖果
for (int i = 1; i < size; ++i ) { // 从左到右
if (ratings[i] > ratings[i-1]) {
num[i] = num[i-1] + 1;
}
}
for (int i = size-1; i > 0; --i ) { // 从右到左
if (ratings[i] < ratings[i-1]) {
num[i-1] = max(num[i-1],num[i] + 1);
}
}
return accumulate(num.begin(),num.end(),0);
}
};
以上是关于通俗易懂贪心算法一:分配问题的主要内容,如果未能解决你的问题,请参考以下文章