630. Course Schedule III

18 篇文章 0 订阅
16 篇文章 0 订阅

There are n different online courses numbered from 1 to n. Each course has some duration(course length) t and closed on dthday. A course should be taken continuously for t days and must be finished before or on the dth day. You will start at the 1stday.

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
Explanation: 
There're 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.

Note:

  1. The integer 1 <= d, t, n <= 10,000.
  2. You can't take two courses simultaneously.


思路:最开始想贪心,按照各种排序方法来,但是最后都有些case WA
首先,结束时间早的课程要先考虑,至于选还是不选就是另外一回事,因为如果不这样到后面本来可以选的课程由于deadline过了而变得不能选,这也符合人们的一般逻辑,所以排序规则是先按end time排,相同再按照start time排,越小放在数组越前面
这样的话就能写出递归版本,传2个参数:当前的时间 + 从index为i的课程开设选
import java.util.Arrays;
import java.util.Comparator;

/*
 * memo
 */
public class memo {
    public int scheduleCourse(int[][] courses) {
        Arrays.sort(courses, new Comparator<int[]>(){
			@Override
			public int compare(int[] a, int[] b) {
				return a[1] - b[1];
			}
        });
        
        Integer[][] memo = new Integer[courses.length][courses[courses.length - 1][1] + 1];
        return schedule(courses, 0, 0, memo);
    }
    
    public int schedule(int[][] courses, int i, int time, Integer[][] memo) {
        if (i == courses.length)
            return 0;
        if (memo[i][time] != null)
            return memo[i][time];
        int taken = 0;
        if (time + courses[i][0] <= courses[i][1])
            taken = 1 + schedule(courses, i + 1, time + courses[i][0], memo);
        int not_taken = schedule(courses, i + 1, time, memo);
        memo[i][time] = Math.max(taken, not_taken);
        return memo[i][time];
    }
}

即使优化为DP版本,复杂度为O(maxTime * length of courses),都会TLE,

其实排完序后可以one pass就解决了,遍历一遍,每次取到当前位置最贪心的情况,何为最贪心?就是选的课程数目最大,在课程数目一样的情况下,结束时间最早(这样就有利于后面的选课),为什么这样贪心是全局最优解呢?假设我们求得i位置的最贪心结果,现在要求i+1位置的最贪心结果
1. 当i+1课程能选我们就先选,贪心使然
2. 如果不能选,我们就尽量把修完课程的时间降到最小(把课程安排的最紧凑),即如果当前课程需要的duration比之前能选的课程最大的duration小,那我们情愿选当前这个,因为这样到目前为止,这样是选课程数目最大,结束时间最早的最优选择(即最贪心的选择),而且一定选的上,因为当前课程结束时间比前面的都大(排过序的),
而且删除之前duration最大也一定只能再加第i+1课程,i+1之前的一定不能加,否则违背之前是最紧凑的贪心情况这一约束

至于怎么快速求出之前最大的duration,用优先队列
/*
 * greedy & priorityQueue
 */
public class Solution {
    public int scheduleCourse(int[][] courses) {
        Arrays.sort(courses, new Comparator<int[]>(){
			@Override
			public int compare(int[] a, int[] b) {
				return a[1] - b[1];	// 相等再按照默认第一位排序
			}
        });
        
        // 把最大的duration放在顶端,这样当来一个课程放不下时就把最大的duration弹出
        PriorityQueue<Integer> pq = new PriorityQueue<Integer>(10, new Comparator<Integer>(){
			@Override
			public int compare(Integer o1, Integer o2) {
				return o2-o1;
			}
        });
        
        int time = 0;
        for(int[] c : courses) {
        	// 能插进pq就插,不能就尽量把pq弄紧凑点
        	if(time + c[0] <= c[1]) {
        		pq.add(c[0]);
        		time += c[0];
        	} else if(!pq.isEmpty() && pq.peek() > c[0]) {
        		time += c[0] - pq.poll();
        		pq.add(c[0]);
        	}
        }
        
        return pq.size();
    }
}

话说怎么LC有那么详细的解答了

import heapq

class Solution:
    def scheduleCourse(self, courses):
        """
        :type courses: List[List[int]]
        :rtype: int
        """
        pq = []
        time = 0
        courses.sort(key=lambda a: a[1])
        
        for t, end in courses:
            if time+t <= end:
                heapq.heappush(pq, -t)
                time += t
            elif pq and pq[0]<-t:
                time -= -t-heapq.heappop(pq)
                heapq.heappush(pq, -t)
        
        return len(pq)
    
s=Solution()
print(s.scheduleCourse([[7,16],[2,3],[3,12],[3,14],[10,19],[10,16],[6,8],[6,11],[3,13],[6,16]]))
(1)Python heapq没有peek,但是pq【0】总是最小的:https://stackoverflow.com/questions/1750991/peeking-in-a-heap-in-python
(2)list[list].sort lambda表达式里面不要对list展开

(3)用个负号就不用自定义排序规则了

(3)上诉代码还可以优化,先把-t加到pq里面

def scheduleCourse(self, A):
    pq = []
    start = 0
    for t, end in sorted(A, key = lambda (t, end): end):
        start += t
        heapq.heappush(pq, -t)
        while start > end:
            start += heapq.heappop(pq)
    return len(pq)





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Java中,ClassNotFoundException是一种异常类型,表示在运行时找不到指定的类。当使用Class.forName()方法或ClassLoader.loadClass()方法加载类时,如果找不到指定的类,就会抛出ClassNotFoundException异常。 对于你提到的ClassNotFoundException: CourseSchedule异常,它表示在运行时无法找到名为CourseSchedule的类。这可能是由于以下几个原因导致的: 1. 类名拼写错误:请确保你输入的类名正确无误。Java对类名是区分大小写的,所以请检查类名的大小写是否与实际类名一致。 2. 缺少依赖:如果CourseSchedule类依赖于其他类或库,而这些依赖项没有正确地被包含在项目中,就会导致ClassNotFoundException异常。请确保所有依赖项都已正确添加到项目中。 3. 类路径问题:如果CourseSchedule类所在的包或目录没有被正确地包含在类路径中,也会导致ClassNotFoundException异常。请检查类路径设置,确保包含了CourseSchedule类所在的路径。 解决这个问题的方法取决于你的具体情况。如果是第一种情况,你可以检查类名的拼写是否正确。如果是第二种情况,你需要确保所有依赖项都已正确添加到项目中。如果是第三种情况,你需要检查类路径设置是否正确。 如果你能提供更多的上下文信息,比如你是在什么情况下遇到这个异常,以及你的代码或项目结构,我可以给出更具体的解决方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值