zoukankan      html  css  js  c++  java
  • Leetcode 630.课程表III

    课程表III

    这里有 n 门不同的在线课程,他们按从 1 到 n 编号。每一门课程有一定的持续上课时间(课程时间)t 以及关闭时间第 d 天。一门课要持续学习 t 天直到第 d天时要完成,你将会从第 1 天开始。

    给出 n 个在线课程用 (t, d) 对表示。你的任务是找出最多可以修几门课。

       

    示例:

    输入: [[100, 200], [200, 1300], [1000, 1250], [2000, 3200]]

    输出: 3

    解释:

    这里一共有 4 门课程, 但是你最多可以修 3 门:

    首先, 修第一门课时, 它要耗费 100 天,你会在第 100 天完成, 在第 101 天准备下门课。

    第二, 修第三门课时, 它会耗费 1000 天,所以你将在第 1100 天的时候完成它, 以及在第 1101 天开始准备下门课程。

    第三, 修第二门课时, 它会耗时 200 天,所以你将会在第 1300 天时完成它。

    第四门课现在不能修,因为你将会在第 3300 天完成它,这已经超出了关闭日期。

       

    提示:

    1. 整数 1 <= d, t, n <= 10,000 。
    2. 你不能同时修两门课程。

    结束时间早的课程要先考虑,至于选还是不选就是另外一回事,因为如果不这样到后面本来可以选的课程由于deadline过了而变得不能选,这也符合人们的一般逻辑,所以排序规则是先按end time排

    排完序后可以one pass就解决了,遍历一遍,每次取到当前位置最贪心的情况,何为最贪心?就是选的课程数目最大,在课程数目一样的情况下,结束时间最早(这样就有利于后面的选课),为什么这样贪心是全局最优解呢?假设我们求得i位置的最贪心结果,现在要求i+1位置的最贪心结果

    1. 当i+1课程能选我们就先选,贪心使然

    2. 如果不能选,我们就尽量把修完课程的时间降到最小(把课程安排的最紧凑),即如果当前课程需要的duration比之前能选的课程最大的duration小,那我们情愿选当前这个,因为这样到目前为止,这样是选课程数目最大,结束时间最早的最优选择(即最贪心的选择),而且一定选的上,因为当前课程结束时间比前面的都大(排过序的),

    而且删除之前duration最大也一定只能再加第i+1课程,i+1之前的一定不能加,否则违背之前是最紧凑的贪心情况这一约束

    至于怎么快速求出之前最大的duration,用优先队列

     

     1 import java.util.Arrays;
     2 import java.util.Comparator;
     3 import java.util.PriorityQueue;
     4 
     5 /*
     6  * greedy & priorityQueue
     7  */
     8 public class Solution {
     9     public int scheduleCourse(int[][] courses) {
    10         Arrays.sort(courses, new Comparator<int[]>(){
    11             @Override
    12             public int compare(int[] a, int[] b) {
    13                 return a[1] - b[1];    // 相等再按照默认第一位排序
    14             }
    15         });
    16 
    17         // 把最大的duration放在顶端,这样当来一个课程放不下时就把最大的duration弹出
    18         PriorityQueue<Integer> pq = new PriorityQueue<Integer>(10, new Comparator<Integer>(){
    19             @Override
    20             public int compare(Integer o1, Integer o2) {
    21                 return o2-o1;
    22             }
    23         });
    24 
    25         int time = 0;
    26         for(int[] c : courses) {
    27             // 能插进pq就插,不能就尽量把pq弄紧凑点
    28             if(time + c[0] <= c[1]) {
    29                 pq.add(c[0]);
    30                 time += c[0];
    31             } else if(!pq.isEmpty() && pq.peek() > c[0]) {
    32                 time += c[0] - pq.poll();
    33                 pq.add(c[0]);
    34             }
    35         }
    36         return pq.size();
    37     }
    38 }

     

     

  • 相关阅读:
    关于c++中 get 和getline
    使用参数初始化表来实现对数据成员的初始化
    关于c++中运算符重载
    关于c++的友元函数
    C#控制台程序点击后暂停工作
    hhgame
    记字符编码与转义符的纠缠
    如何向非技术人(程序猿)解释SQL注入?
    记VS2013并行编译导致出错的解决过程
    记32位Oracle客户端登录报12560协议适配器错误的解决办法
  • 原文地址:https://www.cnblogs.com/kexinxin/p/10381440.html
Copyright © 2011-2022 走看看