



하드디스크가 작업중이 아닐 때, 요청된 작업들 중 수행 시간이 짧은 작업 요청을 우선적으로 수행해야 return값이 최소가 된다. 이러한 부분은 그리디 알고리즘과 비슷한 면모를 보이는 것 같다.
그렇다면 어떻게 수행 시간이 짧은 것들을 먼저 요청할 수 있을까?
해당 방법 사용 시 jobs의 길이는 1 이상 500 이하이기 때문에 시간복잡도 상으로 문제를 해결하는데 큰 문제는 없어보인다. 그렇지만 별로 효율적인 방법은 아닌 것 같다.
1번 방법과 마찬가지, 효율적인 방법은 아닌 것 같다.
이 방법이 가장 효율적인 방법인 것 같아 해당 방법으로 문제를 풀어보았다.
로직은 아래와 같다.
import java.util.*;
class Solution {
class Pair{
Integer start, length, end;
Pair(Integer start, Integer length){
this.start = start;
this.length = length;
this.end = start + length;
}
}
PriorityQueue<Pair> pq = new PriorityQueue<>(((o1, o2) -> {
if(o1.length == o2.length) return o1.start - o2.start;
return o1.length - o2.length;
}));
public int solution(int[][] jobs) {
int answer = 0;
int next = 0;
int complete = 0;
PriorityQueue<Integer> v[] = new PriorityQueue[500001];
ArrayList<Pair> nextJobs = new ArrayList<>();
for(int[] i : jobs) {
if(v[i[0]] == null) v[i[0]] = new PriorityQueue<>();
v[i[0]].add(i[1]);
}
for (int i = 0; complete < jobs.length; i++) {
// 작업을 수행하고 있지 않은 경우
if (pq.isEmpty()){
if(v[i] == null)
continue;
while(!v[i].isEmpty())
pq.add(new Pair(i, v[i].poll()));
next = pq.peek().end;
continue;
}
// 작업을 수행중인 경우
answer += pq.size() + nextJobs.size();
if(v[i] != null){
while(!v[i].isEmpty())
nextJobs.add(new Pair(i, v[i].poll()));
}
if(i == next) {
pq.remove();
pq.addAll(nextJobs);
nextJobs.clear();
complete++;
if(pq.isEmpty()) continue;
next += pq.peek().length;
}
}
answer /= jobs.length;
System.out.println(answer);
return answer;
}
}
그리디의 느낌이 없진 않은 문제였고, 가독성이 있진 않지만 나름의 효율성 또한 따지며 최적화를 시킨 코드를 작성하느라 조금의 고민을 했던 것 같다.
