一、Problem
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.
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.
Constraints:
1 <= startTime.length == endTime.length == profit.length <= 5 * 10^4
1 <= startTime[i] < endTime[i] <= 10^9
1 <= profit[i] <= 10^4
二、Solution
方法一:
- 定义状态:
- 表示询问到第 份工作时,得到的最大报酬
- 思考初始化:
- 思考状态转移方程:
- ,对于第 份工作,可以选择不做也可以选择做,做的话就要连着前一份工作
- 思考输出:
开始写的是这种,然后很不幸,过不了…
[1,1,1]
[2,3,4]
[5,6,4]
预期:6
输出:11
class Solution {
public int jobScheduling(int[] st, int[] et, int[] pf) {
int n = st.length, f[] = new int[n];
Job[] js = new Job[n];
for (int i = 0; i < n; i++) js[i] = new Job(st[i], et[i], pf[i]);
Arrays.sort(js, (e1, e2) -> e1.e - e2.e);
int pre[] = new int[n];
for (int i = 1; i < n; i++)
for (int j = i-1; j >= 0; j--) if (js[j].e <= js[i].s) {
pre[i] = j;
break;
}
f[0] = js[0].p;
for (int i = 1; i < n; i++) {
f[i] = Math.max(f[i-1], f[pre[i]] + js[i].p);
}
return f[n-1];
}
class Job {
int s, e, p;
Job(int s, int e, int p) {this.s = s;this.e = e;this.p = p;}
Job(){}
}
}
原因是当某些工作的开始时间相同的话,只能选择其中的一份,而下面下标从 1 开始运算的话,相当于增加了一份报酬为 0 的假工作,使得第一份工作可以进行比较,而如果从 0 开始,那么第一份工作将不可以比较。
class Solution {
public int jobScheduling(int[] st, int[] et, int[] pf) {
int n = st.length, f[] = new int[n+1];
Job[] js = new Job[n+1];
js[0] = new Job();
for (int i = 1; i <= n; i++) js[i] = new Job(st[i-1], et[i-1], pf[i-1]);
Arrays.sort(js, (e1, e2) -> e1.e - e2.e);
int pre[] = new int[n+1];
for (int i = 2; i <= n; i++)
for (int j = i-1; j >= 1; j--) if (js[i].s >= js[j].e) {
pre[i] = j;
break;
}
f[1] = js[1].p;
for (int i = 2; i <= n; i++) {
f[i] = Math.max(f[i-1], f[pre[i]] + js[i].p);
}
return f[n];
}
class Job {
int s, e, p;
Job(int s, int e, int p) {this.s = s;this.e = e;this.p = p;}
Job(){}
}
}
复杂度分析
- 时间复杂度: ,
- 空间复杂度: ,
方法二:二分优化
我们对 jobs 数组进行了排序,所以我们可以用二分来查找出工作 的前一份可行的工作来优化 查找前一份工作。
复杂度分析
- 时间复杂度: ,
- 空间复杂度: ,