算法入门篇八 贪心算法

牛客网 左程云老师的算法入门课

贪心算法

贪心算法的解题步骤 

例子 

题目要求

 解题策略

  • 按照结束时间早的会议先安排,比如先安排【2,4】,当4结束了,所有开始时间小于4的全部淘汰,【1,7】、【3,4】,【2,8】,将【5,6】加入安排,将【7,10】加入安排

 代码 

// package class07;
 
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
 
public class Code04_BestArrange {
 
    public static class Program {
        public int start;
        public int end;
 
        public Program(int start, int end) {
            this.start = start;
            this.end = end;
        }
    }
 
    public static class ProgramComparator implements Comparator<Program> {
 
        @Override
        public int compare(Program o1, Program o2) {
            return o1.end - o2.end;
        }
 
    }
 
    public static int bestArrange(Program[] programs, int timePoint) {
        Arrays.sort(programs, new ProgramComparator());
        int result = 0;
        // 从左往右依次遍历所有的会议
        for (int i = 0; i < programs.length; i++) {
            if (timePoint <= programs[i].start) {
                result++;
                timePoint = programs[i].end;
            }
        }
        return result;
    }

    //使用暴力解法
    public static int bestArrangeForce(Program[] programs,int timePoint){
        HashSet<Program> set = new HasgSet<>(Arrays.asList(programs));
    }

    //会议的集合是set,当前时间是timePoint
    //返回集合中最多可以安排几个项目

    public static int process(HashSet<Program>set ,int timepoint){
        HashSet<Program> candidates = new HashSet<>();
        for(Program program : set){
            if(program.start >= timepoint){
                candidates.add(program);
            }
        }
        //tmp只是为了使用迭代器
        HashSet<Program> tmp = new HashSet<>(candidates);
        int result = 0;
        //尝试将每一个项目,作为第一个安排的项目
        for(Program program : tmp){
            candidates.remove(program);
            int next = process(candidates, program.end);
            result = Math.max(result,next+1);
            candidates.add(program);
        }
        return result;
    }
 
    public static void main(String[] args) {
 
    }
 
}
  • 注意事项:对于HashSet集合中的元素,不可以一边遍历一边删除。需要使用一个tmp集合,将满足条件条件的元素放到tmp中,然后遍历tmp集合,删除原有的集合中的元素
  • 例子:将1到8元素放入到集合set中,需要删除集合中小于5的元素,所以遍历set集合,将小于5的元素收集到tmp集合中,然后遍历tmp集合,删除set集合中小于5的元素,最后遍历打印set集合。

代码

 HashSet<Integer> set = new HashSet<>();

        set.add(1);
        set.add(2);
        set.add(3);
        set.add(4);
        set.add(5);
        set.add(6);
        set.add(7);
        set.add(8);

        HashSet<Integer> tmp = new HashSet<>();
        //删除集合中比5小的数
        //不可以一边遍历一边删除元素
        for(Integer i : set){
            if(i < 5){
                tmp.add(i);
            }
        }

        for(Integer i : tmp){
            set.remove(i);
        }

        for(Integer i : set){
            System.out.println(i);
        }
    }

题目要求

给定一个字符串类型的数组str,找到一种拼接方式,使得所有字符串拼接起来形成的字符串具有最小的字典序

  • 字典序:两个字符串在字典中谁先放在前面,谁的字典序就低
  • 思路:两个字符串,str1和str2,如果str1+str2的字典顺序小于str2+str1,则将str1放到str2的前面,否则将str2放到str1的前面
  • 排序具有传递性,不可以歧义,如果是闭环结构是不可以排序的
  • “abc”*“xy”  ==> "abc" * K^2 + "xy" ;* K^2好比与将abc字符串向左边移动2位,K暗指字符串是K进制的数字,数字2是指第二个需要拼接字符串的位数,然后加上字符串xy,整个的过程就像数字运算一样。
  • 使用m(str)= return(K^string长度),所以“abc”*“xy”  ==> "abc" * K^2 + "xy" ==> "abc" * m(xy) + "xy"

代码

package class07;
 
import java.util.Arrays;
import java.util.Comparator;
 
public class Code02_LowestLexicography {
 
    public static class MyComparator implements Comparator<String> {
        @Override
        public int compare(String a, String b) {
            return (a + b).compareTo(b + a);
        }
    }
 
    public static String lowestString(String[] strs) {
        if (strs == null || strs.length == 0) {
            return "";
        }
        Arrays.sort(strs, new MyComparator());
        String res = "";
        for (int i = 0; i < strs.length; i++) {
            res += strs[i];
        }
        return res;
    }
 
    public static void main(String[] args) {
        String[] strs1 = { "jibw", "ji", "jp", "bw", "jibw" };
        System.out.println(lowestString(strs1));
 
        String[] strs2 = { "ba", "b" };
        System.out.println(lowestString(strs2));
 
    }
 
}

图片解析

  • 根据给出的条件a . b 小于等于 b . a 和 b. c 小于等于 c . b得出a . c 小于等于 c . a,根据上面的式子,得出右边的不等式,将第一个不等式的两边减去b 再乘以 c;第二个不等式左右两边 减去c 乘以a ,这样两个式子会产生一个重合的项,链接其余不等式,化简之后就可以得到 m(c)* a + c 小于等于 m(a)*c + a
  •  

比较排序的过程:

分金条问题

思路

  • 利用小根堆来做,每次选取其中最小的两个数,合并成为一个数,放入到堆中,依次类推。当小根堆里面只有一个数字的时候,就是最终的答案。(哈夫曼编码

代码

package class07;
 
import java.util.Comparator;
import java.util.PriorityQueue;
 
public class Code03_LessMoneySplitGold {
 
    public static int lessMoney(int[] arr) {
        PriorityQueue<Integer> pQ = new PriorityQueue<>();
        for (int i = 0; i < arr.length; i++) {
            pQ.add(arr[i]);
        }
        int sum = 0;
        int cur = 0;
        while (pQ.size() > 1) {
            cur = pQ.poll() + pQ.poll();
            sum += cur;
            pQ.add(cur);
        }
        return sum;
    }
 
    public static class MinheapComparator implements Comparator<Integer> {
 
        @Override
        public int compare(Integer o1, Integer o2) {
            return o1 - o2; // < 0  o1 < o2  负数
        }
 
    }
 
    public static class MaxheapComparator implements Comparator<Integer> {
 
        @Override
        public int compare(Integer o1, Integer o2) {
            return o2 - o1; // <   o2 < o1
        }
 
    }
 
    public static void main(String[] args) {
        // solution
        int[] arr = { 6, 7, 8, 9 };
        System.out.println(lessMoney(arr));
 
        int[] arrForHeap = { 3, 5, 2, 7, 0, 1, 6, 4 };
 
        // min heap
        PriorityQueue<Integer> minQ1 = new PriorityQueue<>();
        for (int i = 0; i < arrForHeap.length; i++) {
            minQ1.add(arrForHeap[i]);
        }
        while (!minQ1.isEmpty()) {
            System.out.print(minQ1.poll() + " ");
        }
        System.out.println();
 
        // min heap use Comparator
        PriorityQueue<Integer> minQ2 = new PriorityQueue<>(new MinheapComparator());
        for (int i = 0; i < arrForHeap.length; i++) {
            minQ2.add(arrForHeap[i]);
        }
        while (!minQ2.isEmpty()) {
            System.out.print(minQ2.poll() + " ");
        }
        System.out.println();
 
        // max heap use Comparator
        PriorityQueue<Integer> maxQ = new PriorityQueue<>(new MaxheapComparator());
        for (int i = 0; i < arrForHeap.length; i++) {
            maxQ.add(arrForHeap[i]);
        }
        while (!maxQ.isEmpty()) {
            System.out.print(maxQ.poll() + " ");
        }
 
    }
 
}

求获取的最大钱数

例子 

  • 按照花费的钱建立小根堆,这个是被锁定的状态,根据初始的钱,比如w=2,解锁(1,3)和(2,6) ,按照利润的高低,压入利润大根堆中,(2,6)(1,3)加入栈中,然后将其从小根堆中删除。然后做第一个项目(2,6),此时自己的钱数为8,那么将小于8的花费的项目解锁,以此类推。

代码

package class07;
 
import java.util.Comparator;
import java.util.PriorityQueue;
 
public class Code05_IPO {
 
    public static class Node {
        public int p;
        public int c;
 
        public Node(int p, int c) {
            this.p = p;
            this.c = c;
        }
    }
 
    public static class MinCostComparator implements Comparator<Node> {
 
        @Override
        public int compare(Node o1, Node o2) {
            return o1.c - o2.c;
        }
 
    }
 
    public static class MaxProfitComparator 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[] Capital) {
        PriorityQueue<Node> minCostQ = new PriorityQueue<>(new MinCostComparator());
        PriorityQueue<Node> maxProfitQ = new PriorityQueue<>(new MaxProfitComparator());
        // 所有项目扔到被锁池中, 花费组织的小根堆
        for (int i = 0; i < Profits.length; i++) {
            minCostQ.add(new Node(Profits[i], Capital[i]));
        }
        for (int i = 0; i < k; i++) { // 进行K轮
            // 能力所及的项目,全解锁
            while (!minCostQ.isEmpty() && minCostQ.peek().c <= W) {
                maxProfitQ.add(minCostQ.poll());
            }
            if (maxProfitQ.isEmpty()) {
                return W;
            }
            W += maxProfitQ.poll().p;
        }
        return W;
    }
 
}

猜你喜欢

转载自blog.csdn.net/CHYabc123456hh/article/details/106747950