算法篇——贪心算法(基于优先队列)

576 阅读2分钟

贪心后悔法:

总的来说就是贪心+优先队列;题目大概都是有两个限制条件,然后给一个排序,另一个条件进行判断队列大小;

优先队列的底层就是一个小根堆,插入数据的时候就会自动调整堆,总是让最小的元素放在前面。

(哪个放在前面却决于你自己定义的Comparator比较器)

优先级队列 PriorityQueue

PriorityQueue 类在 Java 1.5 中引入。

PriorityQueue 是基于优先堆的一个无界队列,这个优先队列中的元素可以默认自然排序或者通过提供的 Comparator 在队列实例化的时排序。

PriorityQueue 不允许空值,而且不支持 non-comparable(不可比较)的对象,比如用户自定义的类。优先队列要求使用 Java Comparable 和 Comparator 接口给对象排序,并且在排序时会按照优先级处理其中的元素。

PriorityQueue 的大小是不受限制的,但在创建时可以指定初始大小。当我们向优先队列增加元素的时候,队列大小会自动增加。

PriorityQueue 是非线程安全的,所以 Java 提供了 PriorityBlockingQueue(实现 BlockingQueue接口)用于Java 多线程环境。

后悔法的例题

image-20201030112725165

import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;

/**
 * @author SJ
 * @date 2020/10/31
 */
public class ActivityArrange {
    public static void main(String[] args) {
        //建测试数据
        Activity.newActivities();
        //  Activity.print();
        //开始安排
        Queue<Activity> activities = arrangeActivities();
        int totalProfit = 0;
        for (Activity activity : activities) {
            totalProfit += activity.profit;
            System.out.println(activity.toString());

        }
        System.out.println("能获得的最大利润为:" + totalProfit);

    }

    public static class Activity {
        public int ddl;
        public int profit;
        public static Queue<Activity> activities = new PriorityQueue<>(new Comparator<Activity>() {
            @Override
            public int compare(Activity o1, Activity o2) {
                return o1.ddl - o2.ddl;
            }
        });

        @Override
        public String toString() {
            return "Activity{" +
                    "ddl=" + ddl +
                    ", profit=" + profit +
                    '}';
        }

        public Activity(int ddl, int profit) {
            this.ddl = ddl;
            this.profit = profit;
        }

        public static void newActivities() {
            activities.add(new Activity(2, 10));
            activities.add(new Activity(1, 5));
            activities.add(new Activity(1, 7));
        }

        //测试队列
        public static void print() {
            for (Activity activity : activities) {
                System.out.println(activity);
            }
        }
    }

    public static Queue<Activity> arrangeActivities() {
        Queue<Activity> temp = Activity.activities;
        Comparator<Activity> activityComparator = (o1, o2) -> o1.ddl - o2.ddl;
        //temp里面队头放截至是建最前的,从前往后往arrange里面安排
        //队头放截止时间最晚的。
        Queue<Activity> arrange = new PriorityQueue<>(activityComparator.reversed());


        while (!temp.isEmpty()) {
            Activity currentActivity = temp.poll();//取出队头元素并删除
            if (!arrange.isEmpty()) {
                //ddl相同的,如果即将进队的活动的利润比当前队列里活动的利润大,队列里那个活动删掉,把新的活动加进去。
                if (arrange.peek().ddl == currentActivity.ddl && arrange.peek().profit < currentActivity.profit) {
                    arrange.poll();
                    arrange.add(currentActivity);

                } else
                    arrange.add(currentActivity);

            } else {

                arrange.add(currentActivity);

            }
            // temp.poll();

        }
        return arrange;
    }

}

测试结果:

"C:\Program Files\Java\jdk1.8.0_131\bin\java.exe"...
Activity{ddl=2, profit=10}
Activity{ddl=1, profit=7}
能获得的最大利润为:17

Process finished with exit code 0