630. Course Schedule III
来源:互联网 发布:云计算公司怎么盈利 编辑:程序博客网 时间:2024/06/10 20:20
There are n
different online courses numbered from 1
to n
. Each course has some duration(course length) t
and closed on dth
day. A course should be taken continuously for t
days and must be finished before or on the dth
day. You will start at the 1st
day.
Given n
online courses represented by pairs (t,d)
, your task is to find the maximal number of courses that can be taken.
Example:
Input: [[100, 200], [200, 1300], [1000, 1250], [2000, 3200]]Output: 3Explanation: There're totally 4 courses, but you can take 3 courses at most:First, take the 1st course, it costs 100 days so you will finish it on the 100th day, and ready to take the next course on the 101st day.Second, take the 3rd course, it costs 1000 days so you will finish it on the 1100th day, and ready to take the next course on the 1101st day. Third, take the 2nd course, it costs 200 days so you will finish it on the 1300th day. The 4th course cannot be taken now, since you will finish it on the 3300th day, which exceeds the closed date.
Note:
- The integer 1 <= d, t, n <= 10,000.
- You can't take two courses simultaneously.
思路:最开始想贪心,按照各种排序方法来,但是最后都有些case WA
首先,结束时间早的课程要先考虑,至于选还是不选就是另外一回事,因为如果不这样到后面本来可以选的课程由于deadline过了而变得不能选,这也符合人们的一般逻辑,所以排序规则是先按end time排,相同再按照start time排,越小放在数组越前面
这样的话就能写出递归版本,传2个参数:当前的时间 + 从index为i的课程开设选
import java.util.Arrays;import java.util.Comparator;/* * memo */public class memo { public int scheduleCourse(int[][] courses) { Arrays.sort(courses, new Comparator<int[]>(){@Overridepublic int compare(int[] a, int[] b) {return a[1] - b[1];} }); Integer[][] memo = new Integer[courses.length][courses[courses.length - 1][1] + 1]; return schedule(courses, 0, 0, memo); } public int schedule(int[][] courses, int i, int time, Integer[][] memo) { if (i == courses.length) return 0; if (memo[i][time] != null) return memo[i][time]; int taken = 0; if (time + courses[i][0] <= courses[i][1]) taken = 1 + schedule(courses, i + 1, time + courses[i][0], memo); int not_taken = schedule(courses, i + 1, time, memo); memo[i][time] = Math.max(taken, not_taken); return memo[i][time]; }}
即使优化为DP版本,复杂度为O(maxTime * length of courses),都会TLE,
其实排完序后可以one pass就解决了,遍历一遍,每次取到当前位置最贪心的情况,何为最贪心?就是选的课程数目最大,在课程数目一样的情况下,结束时间最早(这样就有利于后面的选课),为什么这样贪心是全局最优解呢?假设我们求得i位置的最贪心结果,现在要求i+1位置的最贪心结果
1. 当i+1课程能选我们就先选,贪心使然
2. 如果不能选,我们就尽量把修完课程的时间降到最小(把课程安排的最紧凑),即如果当前课程需要的duration比之前能选的课程最大的duration小,那我们情愿选当前这个,因为这样到目前为止,这样是选课程数目最大,结束时间最早的最优选择(即最贪心的选择),而且一定选的上,因为当前课程结束时间比前面的都大(排过序的),
而且删除之前duration最大也一定只能再加第i+1课程,i+1之前的一定不能加,否则违背之前是最紧凑的贪心情况这一约束
至于怎么快速求出之前最大的duration,用优先队列
/* * greedy & priorityQueue */public class Solution { public int scheduleCourse(int[][] courses) { Arrays.sort(courses, new Comparator<int[]>(){@Overridepublic int compare(int[] a, int[] b) {return a[1] - b[1];// 相等再按照默认第一位排序} }); // 把最大的duration放在顶端,这样当来一个课程放不下时就把最大的duration弹出 PriorityQueue<Integer> pq = new PriorityQueue<Integer>(10, new Comparator<Integer>(){@Overridepublic int compare(Integer o1, Integer o2) {return o2-o1;} }); int time = 0; for(int[] c : courses) { // 能插进pq就插,不能就尽量把pq弄紧凑点 if(time + c[0] <= c[1]) { pq.add(c[0]); time += c[0]; } else if(!pq.isEmpty() && pq.peek() > c[0]) { time += c[0] - pq.poll(); pq.add(c[0]); } } return pq.size(); }}
话说怎么LC有那么详细的解答了
阅读全文
0 0
- 630. Course Schedule III
- 630. Course Schedule III
- leetcode 630. Course Schedule III
- [LeetCode]630. Course Schedule III
- 630. Course Schedule III 【Hard】 贪心
- Course Schedule III
- Course Schedule III 解法
- 课程调度问题:LeetCode 630. Course Schedule III
- leetcode 630. Course Schedule III 课程调度 + 贪心算法
- 【Course Schedule】Course Schedule
- Course Schedule
- Course Schedule
- Course Schedule
- Course Schedule
- Course Schedule
- Course Schedule
- Course Schedule
- Course Schedule
- 桌面云
- 架构设计:负载均衡层设计方案(1)——负载场景和解决方式
- 关于内存方面的两个小程序
- C++大数问题
- 【0058】java ee第一个项目
- 630. Course Schedule III
- 消息队列探秘-RabbitMQ消息队列介绍
- JSP属性范围
- APM开源产品Pinpoint——Hbase表设计文档
- 关于SQL优化的一些注意事项
- 欢迎使用CSDN-markdown编辑器
- Openstack Ocata安装(Networking Option 2: Self-service networks)
- 常见海量数据问题
- 读《重构:改善既有代码的设计》