贪心算法-详解

前言

顾名思义,贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。如单源最短路经问题,最小生成树问题等。

贪心算法的设计思路
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;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值