There are n
different online courses numbered from 1
to n
. You are given an array courses
where courses[i] = [durationi, lastDayi]
indicate that the ith
course should be taken continuously for durationi
days and must be finished before or on lastDayi
.
You will start on the 1st
day and you cannot take two or more courses simultaneously.
Return the maximum number of courses that you can take.
Example 1:
Input: courses = [[100,200],[200,1300],[1000,1250],[2000,3200]] Output: 3 Explanation: There are 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.
Example 2:
Input: courses = [[1,2]] Output: 1
Example 3:
Input: courses = [[3,2],[4,3]] Output: 0
Constraints:
1 <= courses.length <= 104
1 <= durationi, lastDayi <= 104
This problem asks to find the maximum number of courses that can be taken given constraints on course duration and deadlines. A greedy approach using a priority queue (heap) is efficient for this.
Approach:
Sort by Deadline: The courses are first sorted by their deadlines (lastDay
). This ensures that we consider courses with earlier deadlines first.
Greedy Selection: We iterate through the sorted courses. For each course:
s
.s
exceeds the current course's deadline, we need to remove a course to make room. We remove the longest course from the max-heap (using heappop
or pq.poll()
) and subtract its duration from s
. This ensures we drop the most time-consuming course first.Result: After processing all courses, the size of the priority queue represents the maximum number of courses that could be completed within their deadlines.
Time Complexity: O(N log N), where N is the number of courses. This is dominated by the sorting step (O(N log N)) and the heap operations (O(N log N) in total, as we perform at most N push
and N pop
operations).
Space Complexity: O(N) to store the priority queue (heap) in the worst case (if all courses can be taken).
Code Explanation (Python):
import heapq
class Solution:
def scheduleCourse(self, courses: List[List[int]]) -> int:
courses.sort(key=lambda x: x[1]) #Sort by lastDay
pq = [] # Max-heap to store course durations
s = 0 # Total time spent on courses
for duration, last in courses:
heapq.heappush(pq, -duration) #Negate for max-heap
s += duration
while s > last: #Exceeded deadline
s += heapq.heappop(pq) #Remove longest course
return len(pq) #Number of courses remaining in the heap
The other language implementations follow the same algorithm, using their respective priority queue implementations (e.g., PriorityQueue
in Java, priority_queue
in C++). The Go code uses a custom heap implementation for better performance. The TypeScript solution uses a third-party library for the max priority queue. The core logic remains consistent across all languages.