一千个读者有一千个哈姆雷特,一千个贪心算法题有一千种贪心策略!是不是一下子感觉贪心思想很难?细细回想一下,从小到大你有没有“抄近路”、有没有“贪小便宜”?如果有,恭喜你,你已经具备了“贪心思想”,虽然说贪心策略种类繁多,但是贪心的算法题总共就那么些,我们选择高频的贪心算法题进行掌握,理解其贪心策略,那么很有可能将来某一天考试,你所遇到的贪心算法题就是原题,或者说该题的贪心策略已经掌握只是题目加了“拙劣”的粉饰。
本篇内容主要通过几个简单的贪心问题,引导我们入门贪心,并掌几种贪心策略(切记!这些贪心策略可以当作二级模板来使用)
1.分发饼干
题目见LeetCode455。
题目分析:现在如果若干饼干种有一块较大的饼干,能同时满足胃口大的孩子和胃口小的孩子,那么该将饼干分配给谁呢?很明显,应该把较大的饼干分配给胃口大的孩子,把再小一点的饼干分配给胃口较小的孩子,这就是贪心策略!
理解贪心策略后,直接上代码!
/**
* g胃口,s饼干
* 用大饼干给胃口大的孩子为贪心策略
* 枚举一个最大的饼干,遍历孩子当孩子胃口可以满足的时候,再枚举下一个饼干
* @param g
* @param s
* @return
*/
public static int myFindContentChildren(int[] g, int[] s) {
Arrays.sort(g);
Arrays.sort(s);
int count = 0;
int start = s.length - 1;
for (int i = g.length - 1; i >= 0; i--) {
if(start >= 0 && g[i] <= s[start]){
count++;
start--;
}
}
return count;
}
2.柠檬水找零
题目见LeetCode860。
题目分析:如果收款5元则直接入帐,无需找零;如果收款10元,需要找零5元;如果收款20,找零策略1:找零10元一张和5元一张 找零策略2:找零5元三张。那么,对于收款20元找零的问题,应该选择找零策略1还是找零策略2呢?答:贪心策略:找零10元一张和5元一张(优先花掉10元现金,5元现金的流通性更大更灵活)
理解贪心策略后,直接上代码!
/**
* 分析:收取10元,需要有5元库存
* 收取20元,需要有10元、5元库存 或 5元、5元、5元库存
* 贪心策略,当收取到20元的时候,优先使用10元钞票,因为5元钞票更万能
* @param bills
* @return
*/
public static boolean myLemonadeChange(int[] bills) {
int cash_5 = 0;
int cash_10 = 0;
for (int i = 0; i < bills.length; i++) {
if(bills[i] == 5)
cash_5++;
else if(bills[i] == 10){
cash_5--;
cash_10++;
}else{
if(cash_10 > 0){
cash_10--;
cash_5--;
}else{
cash_5 -= 3;
}
}
if(cash_5 < 0 || cash_10 < 0) return false;
}
return true;
}
3.分发糖果
题目见LeetCode135。
题目分析:首先,需要保证每个人都分到一枚糖果,然后根据得分不同分发剩余的糖果。先从从左侧到右侧观察得分序列,当右侧得分>左侧得分,右侧应该奖励的糖果数量比左侧多1;再从右侧到左侧同样的道理,最终糖果数量应该是左侧遍历一遍和右侧遍历一遍应得糖果的最大值。这样就可以使得糖果最少,即贪心策略!
理解贪心策略后,直接上代码!
/**
* 从左侧到右侧观察得分序列,当右侧得分>左侧得分,右侧应该奖励的糖果数量比左侧多1
* 从右侧到左侧同样的道理
* 最终糖果数量应该是左侧遍历一遍和右侧遍历一遍应得糖果的最大值
* @param ratings
* @return
*/
public static int myCandy(int[] ratings) {
int[] candyArray = new int[ratings.length];
candyArray[0] = 1;
for (int i = 1; i < candyArray.length; i++) {
if(ratings[i] > ratings[i - 1]){
candyArray[i] = candyArray[i-1] + 1;
}else{
candyArray[i] = 1;
}
}
for (int i = candyArray.length - 2; i >= 0; i--) {
if(ratings[i] > ratings[i + 1]){
candyArray[i] = Math.max(candyArray[i + 1] + 1, candyArray[i]);
}else{
candyArray[i] = Math.max(1, candyArray[i]);
}
}
int ans = 0;
for (int candy : candyArray) {
ans += candy;
}
return ans;
}
OK,《算法通关村第十七关——滑动窗口青铜挑战笔记》结束,喜欢的朋友三联加关注!关注鱼市带给你不一样的算法小感悟!(幻听)
再次,感谢鱼骨头教官的学习路线!鱼皮的宣传!小y的陪伴!ok,拜拜,第十七关第二幕见!