D1-贪心算法-分配问题
何为贪心
1、顾名思义,贪心算法采用贪心的策略,保证每次操作都是局部最优的,从而使最
后得到的结果是全局最优的。
2、贪心算法使用原则
1、最优子结构:规模较大的问题的解由规模较小的子问题的解组成,规模较大的问题的解只由其中一个规模较小的子问题的解决定;
2、无后效性:后面阶段的求解不会修改前面阶段已经计算好的结果;
3、贪心选择性质:从局部最优解可以得到全局最优解。
力扣455. 分发饼干
题目链接:455. 分发饼干
思路
1、明确本题目标:用手里的饼干,满足尽可能多的孩子
2、根据上面的目标,我们必须利用好手里的饼干,不能出现,孩子的胃口是1,有2/3/4大小的饼干,我们就要避免"浪费",所以就要给孩子最接近他胃口的饼干
3、这样,每个人都可以获得最接近他胃口的饼干,都不会造成"浪费",才能让更多的人得到饼干,这就是本题的贪心策略。
注意:
1、这种题,明显存在数组,并且我们解题需要使用到数组之中数字关系
2、但是,数组之中,是乱序,一定记住这个大原则:乱序会让时间复杂度最糟糕!
3、所以,第一步就是对两个数组进行排序
4、这样,从胃口最小的孩子入手,当前饼干连这个孩子都满足不了,则说明一定是无用饼干,就看下一个饼干去;若能满足,则一定是最优的。
代码
class Solution {
public:
int findContentChildren(vector<int>& g, vector<int>& s) {
sort(s.begin(), s.end());//排序
sort(g.begin(), g.end());
int i = 0, j = 0;//分别指向数组g s
int g_size = g.size(), s_size = s.size();
int ans = 0;//答案
while (i < g_size&&j < s_size) {
if (s[j] < g[i]) {//当前饼干连胃口最小的孩子都满足不了,一定不能满足任何一个孩子
j++;
continue;
}
else {//当前饼干一定是最适合当前胃口的孩子,并且之后的饼干一定大于了当前饼干造成了浪费,所以选后面的饼干会造成满足孩子的数量减少
ans++;
i++;
j++;
}
}
return ans;
}
};
力扣135. 分发糖果
题目链接:135. 分发糖果
思路
1、贪心策略
1、根据题意,最开始,为每一个人分配一个糖果
2、比如相邻的两个孩子 A B,无非就是两种情况:左面的人等级高;右面的人等级高。
3、但是在一个等级序列中,我们无法确认,相邻的一对人,属于上面那种情况之一,所以贪心策略就来了:先从左到右,一对一对相邻的看,只要右面的等级高,糖果就多;然后再从右到左,只要左面的等级高,糖果就多。
4、这样扫两遍,就满足题意了
2、因为第一遍扫的时候,大家刚初始化玩,糖果数都是1,所以右面的等级高的话,应得到左面糖果数+1
3、第二遍扫的时候,左面等级高的话,可能本身糖果数就是多的,也可能不多,所以要二者之间取max,保证符合题意
代码
class Solution {
public:
int candy(vector<int>& ratings) {
int ans = 0;
int n = ratings.size();
vector<int> cnt(n, 1);
for (int i = 0; i < n - 1; i++) {//从左到右
if (ratings[i] < ratings[i + 1]) {
cnt[i + 1] = cnt[i] + 1;
}
}
for (int i = n - 1; i > 0; i--) {//从右到左
if (ratings[i - 1] > ratings[i]) {
cnt[i - 1] = max(cnt[i - 1], cnt[i] + 1);
}
}
for (int i = 0; i < n; i++) {
ans += cnt[i];
}
return ans;
}
};