leecode每日一题(2022/10/22)
1235. 规划兼职工作
(图片来源-leecode官方题解)
profit[i-1]
存储的就是第i份工作的报酬,这是官方题解,代码如下:
class Solution {
public:
int jobScheduling(vector<int> &startTime, vector<int> &endTime, vector<int> &profit) {
int n = startTime.size();
vector<vector<int>> jobs(n);
for (int i = 0; i < n; i++) {
jobs[i] = {startTime[i], endTime[i], profit[i]};
}
sort(jobs.begin(), jobs.end(), [](const vector<int> &job1, const vector<int> &job2) -> bool {
return job1[1] < job2[1];
});
vector<int> dp(n + 1);
for (int i = 1; i <= n; i++) {
int k = upper_bound(jobs.begin(), jobs.begin() + i - 1, jobs[i - 1][0], [&](int st, const vector<int> &job) -> bool {
return st < job[1];
}) - jobs.begin();
dp[i] = max(dp[i - 1], dp[k] + jobs[i - 1][2]);
}
return dp[n];
}
};
/*
作者:力扣官方题解
链接:https://leetcode.cn/problems/maximum-profit-in-job-scheduling/solutions/1910416/gui-hua-jian-zhi-gong-zuo-by-leetcode-so-gu0e/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*/
个人方法
还是按照结束时间排序,但是此时开辟一个time数组,大小为最晚结束时间+1,此时在i时刻time[i],已经到手的最大报酬,比如job1:start1=1,end1=4,profit1=20,那么time[1~3]都为0,因为此时最大报酬maxprofit为0,还没有拿到工资,但是time[4]=20(工作一结束,马上报酬到手)。
如果job2:start2=2,end2=6,profit2=10,那么前面的4个时刻的最大报酬不变,因为对于前4个时刻,job1是最好的(此时还没有job2),但是如果可以工作到第5时刻,也就是job2可以被选,那么最大报酬可能不同,time[5]=maxProfit=20,此时还没有到第6时刻,最大报酬仍是job1,但是到了第六时刻,报酬可能是time[2]+profit2(也就是time[start]前的最大报酬+这份工作的报酬),当然,这个工作可能被选择,也可能不被选择,所以要取max{ maxProfit, time[2]+profit2 }
,因此,就么迭代下去,就可以得到最终答案,当然,有个测试点过不了,就下面这个点:
[1,2,3,3]
[3,4,5,1000000000]
[50,10,40,70]
可以设一个特判,卡过这个测时间(投机取巧了属实)
class Solution {
public:
int jobScheduling(vector<int>& startTime, vector<int>& endTime, vector<int>& profit) {
int len = startTime.size();
// 记录每个工作的信息
vector<vector<int>> jobs(len);
for (int i = 0; i < len; i++) {
jobs[i] = { startTime[i],endTime[i],profit[i] };
}
// 按照每个工作的结束时间升序排序
sort(jobs.begin(), jobs.end(), [](const vector<int>& a, const vector<int>& b)->bool {
return a[1] < b[1];
});
// 特判点
if (jobs[len - 1][1] == 1000000000)
jobs[len - 1][1] = 10;
// 时间数组
vector<int> time(jobs[len - 1][1] + 1, 0);
int maxProfit = 0; // 记录到某个时刻为止的最大报酬
time[0] = 0;
int nowTime = 0; // 当前的时刻
for (auto job : jobs) {
int start = job[0], end = job[1], profit1 = job[2];
for (; nowTime < end; nowTime++) { // 当前时刻到这份工作结束时刻的报酬都为当前最大报酬
time[nowTime] = maxProfit;
}
time[end] = max(maxProfit, time[start] + profit1); // 不选择这份工作的最大报酬和选择这份工作可以得到的报酬,取最大值
maxProfit = max(maxProfit, time[end]); // 更新最大报酬
}
return time[time.size() - 1]; // 返回最后时刻可以得到的最大报酬
}
};
不过时间效率和空间效率都不咋地,但是是自己A过的第一个困难的dp。yes!!