前言
这篇博客,南国根据自己之前一段时间的学习和刷题,对贪心算法这一知识点做个小的归纳。这篇博客的内容首先是基础知识点,随后是具体的实战习题。话不多说,干货速来~
基础知识点
在计算机专业常见的极大算法里面,贪心算法算是比较好理解的了。一句话用来概括就是,贪心算法:在对问题求解时,总是做出当前看来最好的选择。
这个问题的本质借助的就是贪心算法。考虑当前的决定就是最好的情况。
贪心有许多非常经典的应用,例如说霍夫曼编码,最小生成树算法,Dijkstra单源最短路径等。
其实对于贪心算法,总结的概括性话并不多。它并不像动态规划那样有我们常说的“一个模型三个特征”,也不像回溯算法那样需要递归。关于这两个 在后续博客中,南国有时间会在继续更新。当然不是所有用贪心算法解决的问题他都是给出了最优解。
接下来,我们就通过一些实战的题目来进行算法具体讲解。
实战习题
1.分配饼干
leetcode 455 Assign Cookies
这是非常经典的一道贪心算法的题,难度不大。
解题思路:给一个孩子的饼干应当尽量小又能满足该孩子,这样大饼干就能拿来给满足度比较大的孩子。因为最小的孩子最容易得到满足,所以先满足最小的孩子。
证明:假设在某次选择中,贪心策略选择给当前满足度最小的孩子分配第 m 个饼干,第 m 个饼干为可以满足该孩子的最小饼干。假设存在一种最优策略,给该孩子分配第 n 个饼干,并且 m < n。我们可以发现,经过这一轮分配,贪心策略分配后剩下的饼干一定有一个比最优策略来得大。因此在后续的分配中,贪心策略一定能满足更多的孩子。也就是说在这个问题中不存在比贪心策略更优的策略,即贪心策略就是最优策略。
所以我们首先对两个数组进行升序排序好,然后尝试着把最小的饼干分配给需求最小的小孩,这样逐次对应,求出最多可以满足多少个小孩。
Java实现代码:
package GreedyAlgorithm;
import java.util.Arrays;
/**
* leetcode 455 Assign Cookies
* @author xjh 2019.02.27
* 贪心算法的典型案例 经常看 经常做!!
*/
public class t455_AssignCookies {
public int findContentChildren(int[] g, int[] s) {
//1.首先对两个数组及逆行排序
Arrays.sort(g);Arrays.sort(s);
int gi=0,si=0;
while (gi<g.length&&si<s.length){
if (g[gi]<=s[si]) gi++; //比较遍历到的最小值
si++;
}
return gi;
}
}
2.不重叠区间个数
leetcode 435 Non-overlapping Intervals
题目的要求是给定一组区间,找出需要删除的最小区间个数,以使其余的区间不重叠。
解题思路:
想要找到删除空间的最小个数count,对应的就是找到最多能组成不重叠的个数m 这m个区间去填满从最小下标到最大下标的值。count=n-m
在每次选择时,区间的结尾很重要,结尾越小,留给后面的空间越大,则m也会越大,count就越小。
Java实现代码:
package GreedyAlgorithm;
import java.util.Arrays;
import java.util.Comparator;
/**
* leetcode 435 Non-overlappingIntervals
* 贪心算法的典型案例:计算让一组区间不重叠所需要移除的区间个数。[经常练习 回顾]
* 首先需要计算出最多的可不重叠的区间个数m 然后总个数n减去m
* 计算m 采用贪心算法:我们每次选择的时候,左端点跟前面的已经覆盖的区间不重合的,
* 右端点又尽量小的,这样可以让剩下的未覆盖区间尽可能的大,就可以放置更多的区间。
* @author xjh 2019.02.27
*/
public class t435_NonoverlappingIntervals {
public class Interval {
int start;
int end;
Interval() { start = 0; end = 0; }
Interval(int s, int e) { start = s; end = e; }
}
public int eraseOverlapIntervals(Interval[] intervals) {
if (intervals.length==0||intervals.length==1) return 0;
//1.贪心的第一步 首先需要对区间end进行排序 这里是升序
Arrays.sort(intervals, new Comparator<Interval>() {
@Override
public int compare(Interval o1, Interval o2) {
return o1.end-o2.end;
}
});
//上面这个排序语句 可以用lambda表达式简写为:
//Arrays.sort(intervals,Compar