Greedy Algorithm
标志
- 出现在满足限制值的情况下,期望值最大、至少、最多、最短等关键词
- 每一步的最优选择会让最终值最优(这个才是贪心算法的灵魂)
- 举两个栗子验证,成功则使用贪心算法
这种问题就不能使用贪心算法,因为每步最优并不能保证结果最优:
用法
分饼干
题目描述:
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j ,都有一个尺寸 sj 。如果 sj >= gi ,我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
示例 1:
* 输入: [1,2,3], [1,1]
* 输出: 1
/**
* Assign Cookies
*
* @param g 胃口
* @param s 饼干
* @return
*/
//贪心的思想是,用尽量小的饼干去满足小需求的孩子,所以需要进行排序先
public int findContentChildren(int[] g, int[] s) {
int child = 0;
int cookie = 0;
Arrays.sort(g); //先将饼干 和 孩子所需大小都进行排序
Arrays.sort(s);
while (child < g.length && cookie < s.length ){ //当其中一个遍历就结束
if (g[child] <= s[cookie]){ //当用当前饼干可以满足当前孩子的需求,可以满足的孩子数量+1
child++;
}
cookie++; // 饼干只可以用一次,因为饼干如果小的话,就是无法满足被抛弃,满足的话就是被用了
}
return child;
}
区间覆盖
假设我们有 n 个区间,区间的起始端点和结束端点分别是[l1, r1],[l2, r2],[l3, r3],……,[ln, rn]。我们从这 n 个区间中选出一部分区间,这部分区间满足两两不相交(端点相交的情况不算相交),最多能选出多少个区间呢?(比如任务调度、教师排课等等问题)
- 按照起始端点从小到大的顺序对这 n 个区间排序。
- 每次选择左端点跟前面的已经覆盖的区间不重合,右端点尽量小。这样可以让剩下的未覆盖区间尽可能的大,就可以放置更多的区间。这实际上就是一种贪心的选择方法。
霍夫曼编码
- 频率比较多的字符,用稍微短一些的编码;频率比较少的,用稍微长一些的编码。
- 为了防止编码歧义,霍夫曼编码要求各个字符的编码之间,不会出现某个编码是另一个编码前缀的情况。
思考题
- 在一个非负整数 a 中,我们希望从中移除 k 个数字,让剩下的数字值最小,如何选择移除哪 k 个数字呢?
贪心算法每次最优:每次移除最大的一个数字,直至最后一个数字。
- 假设有 n 个人等待被服务,但是服务窗口只有一个,每个人需要被服务的时间长度是不同的,如何安排被服务的先后顺序,才能让这 n 个人总的等待时间最短?
贪心算法每次最优:先服务需要服务时间短的