目录
一、题目
1、题目描述
We have
n
jobs, where every job is scheduled to be done fromstartTime[i]
toendTime[i]
, obtaining a profit ofprofit[i]
.You're given the
startTime
,endTime
andprofit
arrays, return the maximum profit you can take such that there are no two 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 timeX
.
2、接口描述
python3
python
class Solution:
def jobScheduling(self, startTime: List[int], endTime: List[int], profit: List[int]) -> int:
cpp
cpp
class Solution {
public:
int jobScheduling(vector<int>& startTime, vector<int>& endTime, vector<int>& profit) {
}
};
3、原题链接
二、解题报告
1、思路分析
经典区间问题,我们通常处理策略为按照某一端排序
这里按照右端点升序排序
然后定义状态 f[i] 为前 i 个工作所能取得的最大收益
那么f[i + 1] = max(f[i], f[j] + profit[i])
即第 i 个工作选或不选,j要满足endTime[j] <= startTime[i],这个由于我们已经按照右端点升序排序,所以可以二分查找来快速找到 j
2、复杂度
时间复杂度: O(nlogn)空间复杂度:O(n)
3、代码详解
python3
python
class Solution:
def jobScheduling(self, startTime: List[int], endTime: List[int], profit: List[int]) -> int:
p = sorted(zip(startTime, endTime, profit), key=lambda x:x[1])
n = len(p)
f = [0] * (n + 1)
for i, (s, e, w) in enumerate(p):
idx = bisect_left(p, s + 1, key=lambda x: x[1], hi = i)
f[i + 1] = max(f[i], f[idx] + w)
return f[n]
cpp
cpp
class Solution {
public:
int jobScheduling(vector<int>& startTime, vector<int>& endTime, vector<int>& profit) {
int n = startTime.size();
vector<array<int, 3>> p(n);
for (int i = 0; i < n; i ++)
p[i] = { startTime[i], endTime[i], profit[i] };
sort(p.begin(), p.end(), [](const auto& a, const auto& b){
return a[1] < b[1];
});
vector<int> f(n + 1);
for (int i = 0; i < n; i ++){
int idx = lower_bound(p.begin(), p.begin() + i, array<int, 3>{ 0, p[i][0] + 1, 0}, [](const auto& a, const auto& b){
return a[1] < b[1];
}) - p.begin();
f[i + 1] = max(f[i], f[idx] + p[i][2]);
}
return f[n];
}
};