Leetcode 630. 课程表 III
前面两题是拓扑排序,和这题没有实际联系
看起来像 n 个区间,顺序执行,怎么有点像会议安排,结论:贪心,按结束时间排序
具体的,每次从剩下未安排会议中选出最早结束且与已安排会议不冲突的会议;
写了一下:
int scheduleCourse(vector<vector<int>>& courses) {
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq; // 每次从剩下未安排会议中选出最早结束且与已安排会议不冲突的会议;
for(auto &course : courses) {
pq.push(make_pair(course[1], course[0]));
}
int time = 0, cnt = 0;
while(!pq.empty()) {
pair<int, int> cur = pq.top();
pq.pop();
cout << time << " " << cur.first << " " << cur.second << endl;
if(time + cur.second <= cur.first) {
time += cur.second;
cnt++;
}
}
return cnt;
}
测评通过,87/91,[[0,5], [4,6], [2,6]]
,预期是2,我的结果只有1
先按结束时间排序,再依次枚举,
等同于枚举右边界,表示这个时间内可以开的会议数,如果可以开就直接开,如果不能则替换出一个最长的(当最长的大于当前值时)
下面的实现里,此时的优先队列不是剩下会议的,而是已经放入的会议
把每次push和pop的打印出来,就看的很清楚了
class Solution {
public:
// [[0,5], [4,6], [2,6]]
// 将排好的放到优先队列中,当遇到不能直接加的时候,将队列中的最长的课程替换
int scheduleCourse(vector<vector<int>>& courses) {
vector<pair<int, int>> courses_time;
for(auto &course : courses) {
courses_time.push_back(make_pair(course[1], course[0]));
}
sort(courses_time.begin(), courses_time.end());
// 默认顺序是从大到小
priority_queue<int> pq; // 每次从剩下未安排会议中选出最早结束且与已安排会议不冲突的会议;
int time = 0; // 真实使用的时间
for(auto &course : courses_time) {
if(time + course.second <= course.first) {
time += course.second;
pq.push(course.second);
cout << "push: " << course.first << " " << course.second << endl;
} else {
if(!pq.empty()) {
int duration = pq.top();
if(duration > course.second) { // 持续时间
time += course.second;
time -= duration;
cout << "pop: " << pq.top().first << " " << pq.top().second << endl;
pq.pop();
pq.push(course.second);
cout << "push: " << course.first << " " << course.second << endl;
}
}
}
}
return pq.size();
}
};
参考链接:https://segmentfault.com/a/1190000021518503