一、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 數組進行了排序,所以我們可以用二分來查找出工作 的前一份可行的工作來優化 查找前一份工作。
複雜度分析
- 時間複雜度:,
- 空間複雜度:,