前言
顾名思义,贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。如单源最短路经问题,最小生成树问题等。
贪心算法的设计思路
1:先利用暴力解出题目来-对照组
2:利用脑海中的多种贪心算法去验证对照组的答案和案例
3:如果正确直接用这种
4:不要去证明贪心算法为什么正确(也就是说利用你最朴素的思想找到局部最优解,然后循环这个过程即可)
注:贪心算法用的最多的就是排序和堆
贪心算法案例
题目:给你许多会议时间,要求你在规定的时间内,尽可能多的安排会议进行
package TanXin;
import java.util.Arrays;
import java.util.Comparator;
public class BestArrange {
/*最短的会议时间*/
public static class Progam{
public int start;//开始时间
public int end;//结束时间
public Progam(int start, int end) {
this.start = start;
this.end = end;
}
}
public static class ProgramCompare implements Comparator<Progam>{
@Override
public int compare(Progam o1,Progam o2){
return o1.end-o2.end;//小跟堆
}
}
public static int bestArrange(Progam[] progams,int timePoint){
Arrays.sort(progams);
//想法,就是从小往大,尽可能的安排多的会议
int result = 0;
//从左往右一次遍历所有会议
for (int i = 0; i < progams.length; i++) {
if (timePoint <= progams[i].start){
//如果开始时间比现在会议的时间早,就安排它,不是就不安排它
//然后等于这个会议的结束时间,在去看
result++;
timePoint = progams[i].end;
}
}
return result;
}
}
最长字符串
题目: 给你许多的字符串,要求你拼接出一个最长的字符串(后面的字母不能比前面的字母小)
// 给你一个字符串数组,你拼接出一个最长的字符串
public static class MyCompare implements Comparator<String > {
@Override
public int compare(String o1, String o2) {
//判断字典序,而且选出来那个字典序结合后小
return (o1+o2).compareTo(o2+o1);
}
}
public static String lowestString(String[] strs){
if (strs == null || strs.length == 0){
return "";
}
Arrays.sort(strs,new MyCompare());
String res="";
for (int i = 0; i < strs.length; i++) {
res+=strs[i];
}
return res;
}
分割金条问题
给定你一个数组,里面是想要金条长度,每次分割金条花费当前金条本身的长度,要求你求出分割金条的最小花费
这个题目的潜台词是:这个数组的长度之和就是金条的长度
经典的哈夫曼树
public static int lessMoney(int[] arr){
PriorityQueue<Integer> queue=new PriorityQueue<>();
for (int i = 0; i < arr.length; i++) {
queue.add(arr[i]);
}
int sum=0;
int cur=0;
/*哈夫曼树,每次找到2个最小,结合成一个值,扔回去*/
while (queue.size() > 1){
cur = queue.poll()+queue.poll();
sum += cur;
queue.add(cur);
}
return sum;
}
项目利润问题
给你 N个项目,以及项目的花销与利润,还有你最多可以做 K 个项目,和W的初始资金
要求你求出你最后能赚多少钱
解题思路:将花销组成一个小根堆,将能解锁的项目组成一个大根堆,然后从大根堆中找利润最大的做k个
private static class Node{
public int p;//利润
public int c;//花费
public Node(int p, int c) {
this.p = p;
this.c = c;
}
}
//由花销组成的小根堆
private static class MinCostCompare implements Comparator<Node>{
@Override
public int compare(Node o1, Node o2) {
return o1.c-o2.c;
}
}
private static class MaxProfitCompare implements Comparator<Node>{
@Override
public int compare(Node o1, Node o2) {
return o2.p-o1.p;//组建一个由利润组成的大根堆
}
}
public static int findMaximizedCapital(int k,int w,int[] Profits,int[] captal){
/*k 最多做几个项目, w 初始资金,Profits项目的花费 , captal所得的利润*/
PriorityQueue<Node> minQ=new PriorityQueue<>(new MinCostCompare());
PriorityQueue<Node> maxQ=new PriorityQueue<>(new MaxProfitCompare());
for (int i = 0; i < Profits.length; i++) {
minQ.add(new Node(Profits[i],captal[i]));
}
for (int i = 0; i < k; i++) {
//解锁所有我现在能解锁的项目
while (!minQ.isEmpty() && minQ.peek().c <= w){
maxQ.add(minQ.poll());
}
if (maxQ.isEmpty()){
//没项目可以做了,坐不了
return w;
}
w+=maxQ.poll().p;//加上所获得的利润
}
return w;
}