之前介绍过一些排产相关的方法,这次我们来做一些相关的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