天天看點

LeetCode 1235. Maximum Profit in Job Scheduling DP 二分

We have

n

jobs, where every job is scheduled to be done from

startTime[i]

to

endTime[i]

, obtaining a profit of

profit[i]

.

You're given the 

startTime

 , 

endTime

 and

profit

 arrays, you need to output the maximum profit you can take such that there are no 2 jobs in the subset with overlapping time range.

If you choose a job that ends at time

X

 you will be able to start another job that starts at time

X

.

Example 1:

LeetCode 1235. Maximum Profit in Job Scheduling DP 二分
Input: startTime = [1,2,3,3], endTime = [3,4,5,6], profit = [50,10,40,70]
Output: 120
Explanation: The subset chosen is the first and fourth job. 
Time range [1-3]+[3-6] , we get profit of 120 = 50 + 70.
      

Example 2:

LeetCode 1235. Maximum Profit in Job Scheduling DP 二分
Input: startTime = [1,2,3,4,6], endTime = [3,5,10,6,9], profit = [20,20,100,70,60]
Output: 150
Explanation: The subset chosen is the first, fourth and fifth job. 
Profit obtained 150 = 20 + 70 + 60.
      

Example 3:

LeetCode 1235. Maximum Profit in Job Scheduling DP 二分
Input: startTime = [1,1,1], endTime = [2,3,4], profit = [5,6,4]
Output: 6
      

Constraints:

  • 1 <= startTime.length == endTime.length == profit.length <= 5 * 10^4

  • 1 <= startTime[i] < endTime[i] <= 10^9

  • 1 <= profit[i] <= 10^4

---------------------------------------------------------

Some tips:

  • It's easy to come up with DP, f[i][j]=max(f[i-1][j-range]+profit,f[i-1][j]),but use binary tuple to store the results
  • Binary search to find the last <= target, e.g., upper_bound-1
class Solution:
    def jobScheduling(self, startTime, endTime, profit) -> int:
        def upper_bound(lst, tgt):
            l,r = 0,len(lst)-1
            while (l <= r):
                mid = l + ((r-l)>>1)
                if (lst[mid][0] > tgt):
                    r = mid-1
                else:
                    l = mid+1
            return l

        end_list = [[0,0]] #[endtime, accu_profit]
        res = profit[0]

        for et,st,pro in sorted(list(zip(endTime, startTime, profit))):
            base = end_list.pop() if (end_list and end_list[-1][0] == et) else [et, 0]
            pos = upper_bound(end_list, st)-1 #The last <= target
            pre = end_list[pos][1]
            if (pre+pro > base[1]):
                base[1] = max(pre+pro, end_list[-1][1])
            res = max(res, base[1])
            end_list.append(base)
            #print("end_list={0} st={1}".format(end_list, st))
        return res
s = Solution()
print(s.jobScheduling(startTime = [1,2,3,3], endTime = [3,4,5,6], profit = [50,10,40,70]))