JAVA程序设计:课程表 III(LeetCode:630)

这里有 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 <= d, t, n <= 10,000 。
你不能同时修两门课程。

思路:这道题和之前的一道课程表类似,只是呢一个课程表给了每个课程的开始时间和结束时间,针对那道题,我们讨论出的最优思想是按照结束时间从小到大排序,只要当前课程可以上,我们就要加入答案,这样做一定是最优的。但是针对本题,我们最初的贪心思想是不会变的,依旧需要按照截止时间从小到大排序,但是本题没有给我们开始时间,因此,对于每一个课程,只要能在截止时间前上完,都可以对答案产生贡献,因此我们需要考虑怎样安排才能是更优的呢?

 我们可以先从前往后遍历,对于当前课程i,假如我们已经修完的课程总耗时为x,则只要x+本次课程的耗时<=本次课程的截止时间,那么我们就可以去修这门课;呢假如是大于?此时我们一定不修这门课嘛? 如果不修呢你肯定就错啦。我们看下边一个样例: 假如有三门课程信息分别是:[5,5]   [2,6]  [4,6],如果我们按照上述思想,得到的答案一定是1,但是你再仔细看看,其实答案是2呀!为什么呢? 因为虽然后两门课程截止时间晚,但是这两门课程的耗时短呀,呢可能读者又要想了,呢我们按照耗时长短升序排序就好啦,哈哈哈,你这样的话不是走的更偏了嘛,开始就说了,按照截止时间升序排序一定是最优的,但是我们这里需要一点小小的变动对于当前课程,假如在截止时间前无法完成,我们可以考虑去掉一门已经修过的课程,使得我们能够修完这门课,呢我们要去掉那门课呢? 刚才的样例还记得嘛,我们肯定是要找一个耗时长的课程去掉呀!! 好了,本题解决了。

class Solution {
    public int scheduleCourse(int[][] courses) {
        
    	Arrays.parallelSort(courses,(a,b)->a[1]-b[1]);
    	PriorityQueue<Integer> q=new PriorityQueue<Integer>((a,b)->b-a);
    	int time=0;
    	
    	for(int i=0;i<courses.length;i++) {
    		if(time+courses[i][0]<=courses[i][1]) {
    			q.offer(courses[i][0]);
    			time+=courses[i][0];
    		}
    		else if(!q.isEmpty() && q.peek()>courses[i][0]) {
    			time+=courses[i][0]-q.poll();
    			q.offer(courses[i][0]);
    		}
    	}
    	
    	return q.size();
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值