1235. Maximum Profit in Job Scheduling - cocoder39/coco39_LC GitHub Wiki
1235. Maximum Profit in Job Scheduling
Notes 2022:
加入dfs + cache 的做法
class Job:
def __init__(self, startTime: int, endTime: int, profit: int):
self.startTime = startTime
self.endTime = endTime
self.profit = profit
class Solution:
def jobScheduling(self, startTime: List[int], endTime: List[int], profit: List[int]) -> int:
n = len(startTime)
jobs = []
for i in range(n):
job = Job(startTime[i], endTime[i], profit[i])
jobs.append(job)
jobs.sort(key = lambda job: job.startTime)
startTime = [job.startTime for job in jobs]
cache = [-1 for _ in range(n)]
return self.findMaxProfit(jobs, startTime, cache, 0)
def findMaxProfit(self, jobs: List[Job], startTime: List[int], cache: List[int], idx: int) -> int:
if idx == len(jobs):
return 0
if cache[idx] != -1:
return cache[idx]
nextIdx = bisect.bisect_left(startTime, jobs[idx].endTime)
includeIdxProfit = jobs[idx].profit + self.findMaxProfit(jobs, startTime, cache, nextIdx)
excludeIdxProfit = self.findMaxProfit(jobs, startTime, cache, idx+1)
cache[idx] = max(includeIdxProfit, excludeIdxProfit)
return cache[idx]
=============================================
Option 1: DP + binary search T = O(n log n)
0, 1 knapsack
We can either sort the array by start time or end time
-
sort by start time
- to leverage binary search, we need to use end time to compare with sorted start time
- This can give us the index of the next available job j
- form relationship between dp[i] and dp[j] where i < j
- dp[i] is the max profit you can make with using subarray [i ... n-1]. job[i] may not be selected to get dp[i]
-
sort by end time
- to leverage binary search, we need to use start time to compare with sorted end time
- This can give us the index of the last available job j
- form relationship between dp[i] and dp[j] where i > j
- dp[i] is the max profit you can make with using subarray [0 ... i]. job[i] may not be selected to get dp[i]
class Solution:
def jobScheduling(self, startTime: List[int], endTime: List[int], profit: List[int]) -> int:
n = len(startTime)
startTime, endTime, profit = zip(*sorted(zip(startTime, endTime, profit)))
dp = [0] * (n+1)
for i in range(n-1, -1, -1):
j = bisect.bisect_left(startTime, endTime[i])
dp[i] = max(dp[i+1], profit[i] + dp[j])
return dp[0]
class Solution:
def jobScheduling(self, startTime: List[int], endTime: List[int], profit: List[int]) -> int:
n = len(startTime)
startTime, endTime, profit = zip(*sorted(zip(startTime, endTime, profit), key=lambda job: job[1]))
dp = [0]
for i in range(n):
j = bisect.bisect_right(endTime, startTime[i])
dp.append(max(dp[-1], profit[i] + dp[j]))
return dp[-1]
Option 2: DP T = O(N^2)
class Solution:
def jobScheduling(self, startTime: List[int], endTime: List[int], profit: List[int]) -> int:
n = len(startTime)
jobs = []
for i in range(n):
jobs.append((startTime[i], endTime[i], profit[i]))
jobs.sort()
dp = [job[2] for job in jobs]
res = 0
for i in range(n):
for j in range(i):
if jobs[j][1] <= jobs[i][0]:
dp[i] = max(dp[i], dp[j] + jobs[i][2])
res = max(res, dp[i])
return res