1. 分发饼干
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。
对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
示例 1:
输入: g = [1,2,3], s = [1,1]
输出: 1
解释:
你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。
虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。
所以你应该输出1。
分发饼干
1.1 贪心算法
一开始看到的时候,感觉无法处理。这一题得主要思路就是将大的饼干先分给胃口大的孩子,只要这个大的饼干能够大于等于大的胃口,然后再考虑胃口小的孩子。所以先要对数组进行排序,先找两个数组最大的值比较。s[j] >= g[i]是已知条件。
public int findContentChildren(int[] g, int[] s) {
// 排序
Arrays.sort(g);
Arrays.sort(s);
// 计数器
int count =0;
// 尺寸最后一个
int start = s.length-1;
// 遍历孩子胃口,先选最大的
for(int index = g.length-1;index>=0;index--){
// 如果尺寸大于0 并且 当前胃口是小于尺寸的,可以得到满足
if(start>=0 && g[index] <= s[start]){
// 计数器++
count++;
// 往前移
start--;
}
}
return count;
}
但是这里我感觉使用将数组逆序比较好处理。这里面主要是这个数组变量取得名字真的容易看错。
2. 柠檬水找零
柠檬水找0
在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。
每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。
注意,一开始你手头没有任何零钱。
给你一个整数数组 bills ,其中 bills[i] 是第 i 位顾客付的账。如果你能给每位顾客正确找零,返回 true ,否则返回 false 。
2.1 贪心算法
遍历一下账单,分成3种情况,第一种就是正好付5块,不用找,第二种是付10,需要找5,第三种是付20找15,但是这里两种情况,有10和没10,有10再找5,没10找3个5,最后判断10或者5是否还有了,没有了就false。 先不考虑每种情况下是否有对应的零钱,就默认都可以找。这里不使用总金额计算,而是使用5/10的张数作为计算。
public boolean lemonadeChange(int[] bills) {
int cash_5 = 0;
int cash_10 = 0;
for (int i = 0; i < bills.length; i++) {
// 正好5
if (bills[i] == 5) {
cash_5++;
// 给10找5
} else if (bills[i] == 10) {
cash_5--;
cash_10++;
// 給20找15
} else if (bills[i] == 20) {
// 有10,再找5
if (cash_10 > 0) {
cash_10--;
cash_5--;
// 没10,找15
} else {
cash_5 -= 3;
}
}
if (cash_5 < 0 || cash_10 < 0) return false;
}
return true;
}
3. 分发糖果
n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。
你需要按照以下要求,给这些孩子分发糖果:
每个孩子至少分配到 1 个糖果。
相邻两个孩子评分更高的孩子会获得更多的糖果。
请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。
示例 1:
输入:ratings = [1,0,2]
输出:5
解释:你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。
示例 2:
输入:ratings = [1,2,2]
输出:4
解释:你可以分别给第一个、第二个、第三个孩子分发 1、2、1 颗糖果。
第三个孩子只得到 1 颗糖果,这满足题面中的两个条件。
3.1 贪心算法
将这个题目划分成两部分,每个孩子至少分配到 1 个糖果和相邻两个孩子评分更高的孩子会获得更多的糖果。
{1 , 1 , 1, 1}那么每个人能够分到1个糖果,就是4个
{1,2,2,2} 分的糖果数应该是 1,2,1,1,只考虑第一个评分高的。
还有一种情况是{4,3,2,1},如果按照递增的的来分配的话,很显然都不满足,所以糖果数是{1,1,1,1},那么这个时候就要反着来比较,因为反正就是递增的,然后对大的值进行递增。
public int candy(int[] ratings) {
int [] candyRate = new int[ratings.length];
candyRate[0] = 1;
// 左规则,第一个孩子糖果是1,只要是处于递增序列,糖果数就是之前的糖果数+1,否则就将当前糖果数字设置为1
for(int i=1;i<ratings.length;i++){
if(ratings[i] > ratings[i-1]){
candyRate[i] = candyRate[i-1]+1;
}else{
candyRate[i] = 1;
}
}
// 右规则,如果倒数第二个孩子的评分大于倒数第一个孩子评分,那么比较当前孩子的糖果数和下一个孩子的糖果数+1,必须要满足评分高的,获得的糖果数多
for(int i=ratings.length-2;i>=0;i--){
if(ratings[i]>ratings[i+1]){
candyRate[i] = Math.max(candyRate[i],candyRate[i+1]+1);
}
}
int ans =0;
for(int s:candyRate){
ans+=s;
}
return ans;
}
总结
贪心算法并没有什么特殊的算法,主要是根据题目而来,选择出认为当前最合适的方案。