630. 课程表 III
【贪心+排序+优先队列】ci = [di, li],假设存在1,2,3...这样的顺序使得最后产生最优解,那么需要s012:
0 + d0 < l0
0 + d0 + d1 < l1
0 + d0 + d1 + d2 < l2...
如果将0和1交换顺序,那么就变成了s10:
0 + d1 < l1
0 + d1 + d0 < l0
如果在s10成立的情况下s01必然成立(因为s01是最优解,在其他情况下也必须成立)那么我们需要把s01的右边的条件放更宽,需要l1 > l0。验证一下:0 + d1 + d0 < l0成立,因为l1 > l0,那么0 + d1 + d0 < l1必然也成立,0 + d1 + d0 < l0成立,那么0 + d0 < l0必然也成立。
所以按照l进行排序更容易找到最优排列。在已经拍好前i - 1个的情况下,当前为第day天,如果day + di < li,那么第i个可以直接排在后面,并且把day + di;否则,我们应该看看他的d是否比之前序列中的某个d小,这样可以使得总的day更小,更容易比后面的l小。
class Solution {
// 贪心
// 2:32 3:47
// 1 + d0 < l0
// 1 + d0 + d1 < l1
// 1 + d0 + d1 + d2 < l2
// 1 + d0 + d2 < l2
// 1 + d0 + d2 + d1 < l1
public int scheduleCourse(int[][] courses) {
PriorityQueue queue = new PriorityQueue((a, b) -> b[0] - a[0]);
Arrays.sort(courses, (a, b) -> a[1] - b[1]);
int day = 0;
for (var c: courses) {
if (day + c[0] <= c[1]) {
day += c[0];
queue.offer(c);
} else {
if (!queue.isEmpty()) {
var top = queue.peek();
if (top[0] > c[0]) {
day = day - top[0] + c[0];
queue.poll();
queue.offer(c);
}
}
}
}
return queue.size();
}
}
class Solution {
public:
// 4:13 23
int scheduleCourse(vector>& courses) {
sort(courses.begin(), courses.end(), [](const vector& a, const vector& b) {
return a[1] < b[1];
});
priority_queue q;
int day = 0;
for (auto c: courses) {
if (day + c[0] <= c[1]) {
day += c[0];
q.push(c[0]);
} else {
if (!q.empty()){
auto top = q.top();
if (top > c[0]) {
q.pop();
q.push(c[0]);
day = day - top + c[0];
}
}
}
}
return q.size();
}
};