我们来分析一下题目:
courses是一个二维数组。每个小数组中,第一个数值代表:学习该课程的持续时间。第二个数值代表学习该课程的最晚时间。那么我们应该如何优先选择要学习的课程?
例如有两个课程:[1,2] ,[3,6]。
1+3 < 6。那么对于代码而言,我们需要对二维数组courses的第二个值做一个升序排序。然后我们从左往右选择课程去学习。
因此,我们首先应该对二维数组做一个排序:
Arrays.sort(courses, Comparator.comparingInt(a -> a[1]));
我们给个例子,有三个课程:[1,2] 、[3, 4]、[2, 5]。按照截止日期升序排序。
1 + 3 + 2 > 5 ,即第三个课程我们无法学习。那这时候咋办?[3, 4]、[2, 5] 中,我们应该优先选择耗时更短的课程,即 [2,5]。讲到这里,我们就意识到,在程序编码过程中:
// 大根堆,学习时长更长的在堆顶
PriorityQueue<int[]> heap = new PriorityQueue<>((a, b) -> b[0] - a[0]);
// 学习总耗时
int total = 0;
for (int[] c : courses) {
int duration = c[0];
int lastDay = c[1];
if (total + duration <= lastDay) {
// 记录当前的学习总耗时还有课程
total += duration;
heap.offer(c);
} else if (!heap.isEmpty() && heap.peek()[0] > duration) {
// 若当前课程学习不了,那么拿当前堆顶元素(耗时最大)和当前课程的耗时作比较。若当前耗时更短。那么择优选择当前课程
total = total - heap.poll()[0] + duration;
heap.offer(c);
}
}
最后返回堆的大小,即是选择的课程数量:
return heap.size();
完整代码如下:
public class Test630 {
public int scheduleCourse(int[][] courses) {
// 根据第二个值进行升序
Arrays.sort(courses, Comparator.comparingInt(a -> a[1]));
// 大根堆,学习时长更长的在堆顶
PriorityQueue<int[]> heap = new PriorityQueue<>((a, b) -> b[0] - a[0]);
// 学习总耗时
int total = 0;
for (int[] c : courses) {
int duration = c[0];
int lastDay = c[1];
if (total + duration <= lastDay) {
// 记录当前的学习总耗时还有课程
total += duration;
heap.offer(c);
} else if (!heap.isEmpty() && heap.peek()[0] > duration) {
// 若当前课程学习不了,那么拿当前堆顶元素(耗时最大)和当前课程的耗时作比较。若当前耗时更短。那么择优选择当前课程
total = total - heap.poll()[0] + duration;
heap.offer(c);
}
}
return heap.size();
}
}
public class Test630 {
public int scheduleCourse(int[][] courses) {
// 根据第二个值进行升序
Arrays.sort(courses, Comparator.comparingInt(a -> a[1]));
// 大根堆,学习时长更长的在堆顶
PriorityQueue<Integer> heap = new PriorityQueue<>((a, b) -> b - a);
// 学习总耗时
int total = 0;
for (int[] c : courses) {
int duration = c[0], lastDay = c[1];
total += duration;
heap.offer(duration);
if (total > lastDay) {
total -= heap.poll();
}
}
return heap.size();
}
}