Description
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: 3
Analyze
我course schedule又回来了!
有一个简单版的问题,条件改为课程的开始结束时间固定,你不可以提前上课。这个问题的限制多了,解就比较容易找,很明显的贪心算法——按开始时间排序,最早结束时间优先,冲突课程忽略。
对于这道题,我尝试按照最迟开始时间排序然后在冲突课程中选择一个更早结束的,只要在冲突范围外的课程就先不予考虑。但提交后发现这不是正确解法,比如按照这种策略选了一个周期很长的课,可是它的冲突范围之外有好几个很短的课互相冲突,由于前面占去了很长的时间只能从中选一个。那当初选那门长长的课就不如提前上几门短的课。
没时间继续想了,赶紧看别人的Discuss。
Code
取的是讨论区最高票C++解法,然而会有Runtime Error,加上一句判断才对:
if(courses[i][0] > courses[i][1]) continue;
算法解释如下:
First, we sort courses by the end date, this way, when we’re iterating through the courses, we can switch out any previous course with the current one without worrying about end date.
Next, we iterate through each course, if we have enough days, we’ll add it to our multiset. If we don’t have enough days, then we can either ignore this course, or we can use it to replace a longer course we added earlier.
My final consideration was when we replace a longer course with a much shorter one, does that mean we’ll have enough room to take some courses previously ignored for being too long?
The answer is no, because any courses we missed would be longer than what’s in multiset cls. So the increase in number of days cannot be larger than the largest element in cls, and certainly will be less than a previously ignored course which has to be even longer.
class Solution {
public:
int scheduleCourse(vector<vector<int>>& courses) {
sort(courses.begin(),courses.end(),
[](vector<int> a, vector<int> b){return a.back()<b.back();});
multiset<int> cls;
int cursum=0;
for (int i=0; i<courses.size(); i++) {
if(courses[i][0] > courses[i][1]) continue;
if (cursum+courses[i].front()<=courses[i].back()) {
cls.insert(courses[i].front());
cursum+=courses[i].front();
} else if (*cls.rbegin()>courses[i].front()) {
cursum+=courses[i].front()-*cls.rbegin();
cls.erase(--cls.end());
cls.insert(courses[i].front());
}
}
return cls.size();
}
};
Summary
觉得这道题折射出了人生哲理。
我就是一下没想到选了的课还可以退啊!