APS排产相关的leetcode

之前介绍过一些排产相关的方法,这次我们来做一些相关的leetcode,其实是非常简化的scheduling相关方法。

scheduling相关对应顺序和资源选择

1834 Single-Threaded CPU

class Solution:
    def getOrder(self, tasks: List[List[int]]) -> List[int]:
        for i, task in enumerate(tasks):
            task.append(i)
        tasks.sort()
        ans = []
        q = []
        n = len(tasks)
        i = t = 0
        while q or i < n:
            if not q:
                t = max(t, tasks[i][0])
            while i < n and tasks[i][0] <= t:
                heappush(q, (tasks[i][1], tasks[i][2]))
                i += 1
            pt, j = heappop(q)
            ans.append(j)
            t += pt
        return ans

621 Task Scheduler

class Solution:
    def leastInterval(self, tasks: List[str], n: int) -> int:
        count_dict = collections.defaultdict(int)
        for task in tasks:
            count_dict[task] += 1
        
        max_freq = max(count_dict.values())
        max_freq_count = 0
        for key, value in count_dict.items():
            if value == max_freq:
                max_freq_count += 1
        
        res = (max_freq - 1) * (n + 1) + max_freq_count
        return max(res, len(tasks))

630 Course Schedule III

输入: [[100, 200], [200, 1300], [1000, 1250], [2000, 3200]]
输出: 3
说明:
这里总共有 4 节课, 但是你最多可以上 3`节课:
第一, 上第一节课, 需要100天, 所以你会在第100天完成这个课程, 并且在第101天准备上下一节课.
第二, 上第三节课, 需要1000天, 所以你会在第1100天的时候完成这门课, 并且在第1101天准备上下一节课.
第三, 上第二节课, 需要200天, 所以你会在第1300天的时候完成这门课.
现在不能上第4节课, 因为你会在第3300天的时候完成这门课, 但是已经超过关闭日期了
class Solution:
    def schedule_course(self, courses: List[List[int]]) -> int:
        import heapq
        courses.sort(key=lambda c: c[1])  # 按照需求日期排序,

        q = list()
        # 优先队列中所有课程的总时间
        total = 0

        for ti, di in courses:
            if total + ti <= di:
                total += ti
                heapq.heappush(q, -ti)
            elif q and -q[0] > ti:  # 如果对列中的时长比如今这个更大
                total -= -q[0] - ti
                heapq.heappop(q)
                heapq.heappush(q, -ti)

        return len(q)

1029 Two City Scheduling

  • 贪心
class Solution:
    def twoCitySchedCost(self, costs: List[List[int]]) -> int:
        # 主要是差值,其次是绝对值
        cost_diff = [(i - j, i, t) for t, (i, j) in enumerate(costs)]
        cost_diff.sort()

        candidate_t = [i[2] for i in cost_diff]
        res = 0
        for i in candidate_t[: len(costs)//2]:
            res += costs[i][0]
        
        for i in candidate_t[len(costs)//2:]:
            res += costs[i][1]
        return res

1229 Meeting Scheduler

class Solution:
    def earliest_appropriate_duration(self, slots1, slots2, duration):
        index1 = 0
        index2 = 0
        while index1 < len(slots1) and index2 < len(slots2):
            left1, right1 = slots1[index1].start, slots1[index1].end
            left2, right2 = slots2[index2].start, slots2[index2].end
            if (min(right1, right2) - max(left1, left2)) >= duration:
                return Interval(max(left1, left2), max(left1, left2)+duration)
            if right1 < right2:
                index1 += 1
            else:
                index2 += 1
        return Interval(-1, -1)

2365 Task Scheduler II

class Solution:
    def taskSchedulerII(self, tasks: List[int], space: int) -> int:
        my_dict = collections.defaultdict(int)
        time = 0
        for task in tasks:
            time = max(time + 1, my_dict[task])
            my_dict[task] = time + space + 1
        return time

1335 Minimum Difficulty of a Job Schedule

class Solution:
    def minDifficulty(self, jobDifficulty: List[int], d: int) -> int:
        n = len(jobDifficulty)
        if d > n:
            return -1
    
        # dp[i][k] := the minimum difficulty to schedule the first i jobs in k days
        dp = [[math.inf] * (d + 1) for _ in range(n + 1)]
        dp[0][0] = 0
    
        for i in range(1, n + 1):
            for k in range(1, d + 1):
                maxDifficulty = 0  # max(job[j + 1..i])
                for j in range(i - 1, k - 2, -1):  # 1-based
                    maxDifficulty = max(maxDifficulty, jobDifficulty[j])  # 0-based
                    dp[i][k] = min(dp[i][k], dp[j][k - 1] + maxDifficulty)    
        return dp[n][d]

1462 Course Schedule IV

class Solution:
    def checkIfPrerequisite(self, numCourses: int, prerequisites: List[List[int]], queries: List[List[int]]) -> List[bool]:
        graph = collections.defaultdict(list)
        degree = [0] * numCourses
        pre_lookup = collections.defaultdict(set)

        for pre, cur in prerequisites:
            graph[pre].append(cur)
            degree[cur] += 1

        queue = collections.deque([i for i in range(numCourses) if degree[i] == 0])      
        while queue:
            node = queue.popleft()
            for cur in graph[node]:
                pre_lookup[cur].add(node)
                pre_lookup[cur].update(pre_lookup[node])

                degree[cur] -= 1

                if degree[cur] == 0:
                    queue.append(cur)

        res = []
        for q in queries:
            if q[0] in pre_lookup[q[1]]:
                res.append(True)
            else:
                res.append(False)
        return res

207 Course Schedule

class Solution:
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        graph = collections.defaultdict(list)
        degree = [0] * numCourses  # 也可以使用collections.defaultdict(int)

        for (cur, pre) in prerequisites:
            graph[pre].append(cur)  # bfs往后走所以记录后面
            degree[cur] += 1  # 后面是否可开始依赖前面

        start_course = [i for (i, d) in enumerate(degree) if d == 0]
        queue = collections.deque(start_course)
        visited = 0
        while queue:
            cur = queue.popleft()
            visited += 1
            for adj in graph[cur]:  # graph记录后续可以开始的课程
                degree[adj] -= 1  # 后续课程的前依赖 - 1
                if not degree[adj]:
                    queue.append(adj)
        return visited == numCourses

210 Course Schedule II

import collections

class Solution:
    def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:
        courses = collections.defaultdict(set)
        pres = collections.defaultdict(set)

        for (x, y) in prerequisites:
            courses[y].add(x)  # 上完这个课之后可以上的
            pres[x].add(y)  # 这个课程的所有先修课程
        
        no_pre = [i for i in range(numCourses) if not pres[i]]

        res = []
        count = 0
        while no_pre:
            take_course = no_pre.pop()
            count += 1
            res.append(take_course)
            for i in courses[take_course]:
                pres[i].remove(take_course)
                if not pres[i]:
                    no_pre.append(i)
        
        return res if count == numCourses else []

815 Bus Routes

class Solution:
    def numBusesToDestination(self, routes: List[List[int]], source: int, target: int) -> int:
        if source == target:
            return 0
        
        graph = collections.defaultdict(list)
        visited = set()

        for i in range(len(routes)):
            for j in routes[i]:
                # {站点: 所属路线}
                graph[j].append(i)
        
        res = 0
        queue = collections.deque()
        queue.append(source)

        # BFS解法关键在于: 一次加入一个route的stop
        while queue:
            res += 1
            for _ in range(len(queue)):
                node = queue.popleft()
                for stop in graph[node]:
                    if stop in visited:
                        continue
                    visited.add(stop)

                    for next_stop in routes[stop]:
                        if next_stop == target:
                            return res
                        queue.append(next_stop)
        return -1

1235 Maximum Profit in Job Scheduling

class Solution:
    def jobScheduling(self, startTime: List[int], endTime: List[int], profit: List[int]) -> int:
        jobs = sorted(zip(endTime, startTime, profit))
        number_of_jobs = len(profit)
        
        dp = [0] * (number_of_jobs + 1)
        for i, (current_end_time, current_start_time, current_profit) in enumerate(jobs):
            index = bisect.bisect_right(jobs, current_start_time, hi=i, key=lambda x: x[0])
            dp[i + 1] = max(dp[i], dp[index] + current_profit)
        return dp[number_of_jobs]

interval相关对应排产中的资源日历选择

759 Employee Free Time

class Solution:
    def employeeFreeTime(self, schedule):
        import heapq
        heap, result = [], []
        for employee in schedule:
            for i in range(0, len(employee), 2):
                heapq.heappush(heap, (employee[i], 0))
                heapq.heappush(heap, (employee[i + 1], 1))
        
        count, n = 0, len(heap)
        while n > 1:
            left = heapq.heappop(heap)
            right = heap[0]
            if (left[1] == 0):
                count += 1
            else:
                count -= 1
            if left[1] == 1 and right[1] == 0:
                if count == 0:
                    result.append(Interval(left[0], right[0]))
            n = len(heap)
        
        return result

435 Non-overlapping Intervals

class Solution:
    def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
        intervals.sort(key=lambda x: x[0])

        finals = []
        res = 0
        for interval in intervals:
            if not finals or interval[0] >= finals[-1][1]:
                finals.append(interval)
            else:
                res += 1
                finals[-1][1] = min(finals[-1][1], interval[1])
        return res

猜你喜欢

转载自blog.csdn.net/weixin_38812492/article/details/135651530