CodingTest/99클럽2024스터디
99클럽 코테 스터디 29일차 TIL, LeetCode / maximum-profit-in-job-scheduling
mrawesome
2024. 8. 20. 00:02
https://leetcode.com/problems/maximum-profit-in-job-scheduling/
첫번째 시도 : DFS + Memoization
// https://leetcode.com/problems/maximum-profit-in-job-scheduling/description/
/*
1) DFS + Memoization
https://www.youtube.com/watch?v=JLoWc3v0SiE
각 job 에 대해 2가지 선택이 있다.
해당 job 을 선택할지 말지
st time 기준 정렬한다.
만약 해당 job 을 선택하면, 이후에 나오는 job 중에서
앞서 선택한 job 과 겹치는 job 은 선택하지 않는다.
만약 해당 job 을 선택하지 않는다면, 그 다음 st time job 으로
넘어가면 된다.
=> 시간 초과가 발생한다.
왜냐하면 nxtIdx 를 구할 때, o(n) 의 시간이 걸리면서, 뒤에 있는 모든
job 을 확인하는 과정을 거치기 때문이다.
*/
class Solution {
public:
struct Job
{
int st;
int ed;
int profit;
bool operator < (const Job& other)
{
return st < other.st;
}
};
vector<Job> jobs;
vector<int> memoization;
// 해당 idx job 이후의 최대 retVal
int dfs(int idx)
{
if (idx == jobs.size()) return 0;
if (memoization[idx]) return memoization[idx];
int retVal = 0;
// Job include X -> 바로 다음 idx + 1 로 넘어간다.
retVal = dfs(idx + 1);
// Job Include -> 그 다음 가능한 job 의 idx : 'j' 을 선택한 경우
int nxtIdx = idx + 1;
while(nxtIdx < jobs.size())
{
if (jobs[nxtIdx].st >= jobs[idx].ed) break;
nxtIdx += 1;
}
// dfs(nxtIdx) : nxtIdx 에 해당하는 job 을 선택할 수도 있고 선택 안할 수도 있다.
retVal = max(retVal, jobs[idx].profit + dfs(nxtIdx));
memoization[idx] = retVal;
return retVal;
}
int jobScheduling(vector<int>& startTime, vector<int>& endTime, vector<int>& profit) {
vector<int> dp;
jobs.reserve(startTime.size());
memoization.resize(startTime.size());
for (int i = 0; i < startTime.size(); ++i)
jobs.push_back({startTime[i], endTime[i], profit[i]});
sort(jobs.begin(), jobs.end());
return dfs(0);
}
};
결과 : 시간 초과
--------------------
두번째 시도 : DFS + Memoization + 이분탐색
/*
2) 그렇다면, nxtIdx 를 찾는 방식을 이진 탐색으로 변경하면 된다.
*/
class Solution {
public:
struct Job
{
int st;
int ed;
int profit;
bool operator < (const Job& other)
{
return st < other.st;
}
};
vector<Job> jobs;
vector<int> memoization;
// 해당 idx job 이후의 최대 retVal
int dfs(int idx)
{
if (idx == jobs.size()) return 0;
if (memoization[idx]) return memoization[idx];
int retVal = 0;
// Job include X -> 바로 다음 idx + 1 로 넘어간다.
retVal = dfs(idx + 1);
// Job Include -> 그 다음 가능한 job 의 idx : 'j' 을 선택한 경우
int nxtIdx = idx + 1;
// while(nxtIdx < jobs.size())
// {
// if (jobs[nxtIdx].st >= jobs[idx].ed) break;
// nxtIdx += 1;
// }
int st = idx + 1, ed = jobs.size();
while(st <= ed)
{
int mid = (st + ed) / 2;
if (mid == jobs.size())
{
nxtIdx = mid;
break;
}
if (jobs[mid].st >= jobs[idx].ed)
{
nxtIdx = mid;
ed = mid - 1;
}
else
{
st = mid + 1;
}
}
// cout << "idx, nxtIdx : " << idx << "," << nxtIdx << endl;
// dfs(nxtIdx) : nxtIdx 에 해당하는 job 을 선택할 수도 있고 선택 안할 수도 있다.
retVal = max(retVal, jobs[idx].profit + dfs(nxtIdx));
memoization[idx] = retVal;
// cout << "retVal : " << retVal << endl;
return retVal;
}
int jobScheduling(vector<int>& startTime, vector<int>& endTime, vector<int>& profit) {
vector<int> dp;
jobs.reserve(startTime.size());
memoization.resize(startTime.size());
for (int i = 0; i < startTime.size(); ++i)
jobs.push_back({startTime[i], endTime[i], profit[i]});
sort(jobs.begin(), jobs.end());
return dfs(0);
}
// 1 ~ 2 > 5
// 1 ~ 3 > 6
// 1 ~ 4 > 4
};