https://school.programmers.co.kr/learn/courses/30/lessons/176962#
굉장히 까다로운 구현문제다. 여러 조건들이 있고 그 조건을 하나도 빼먹으면 안 되며 문제에 정확히 명시돼있지 않더라도 예외 케이스들을 다 추가해서 구현해야 한다.
배열 VS 우선순위큐
배열을 정렬한 뒤 index를 사용해서 값을 구해도 되고 우선순위큐를 사용해도 되는데 배열을 사용할 경우 까다로운 조건문안에서 매번 index++로 인덱스를 추가관리해야 하기 때문에 우선순위큐를 사용했다.
현재 작업 중인 과제 표시
현재 작업중인 과제를 별도의 변수로 선언하거나 큐에 넣는 방법이 있는데 마찬가지로 까다로운 조건문에서 디버깅하기 편하게 큐를 사용해서 현재 작업 중이라면 q에 값을 넣기로 했다.
조건을 나누는 방식
이 부분은 정답은 없다. 다만 최대한 깔끔하게 보이기 위해서 if와 else 하나로 크게 나눠지도록 구성했다. 현재 작업 중인 과제가 없다면(큐가 비었다면)과 현재 작업중인 과제가 있다면으로 크게 두개로 나누고 세부요소들을 if else를 더 넣어서 구현하도록 설계했다. if를 수행하고 나면 작업중인 과제가 추가돼고 else를 수행하면 작업중인 과제가 삭제된다.
간단하게 적었던 논리 흐름을 적자면
if -> 현재 진행 중인 과제가 없다면 => 해당 if의 목적은 큐에 작업과제 추가
pq만 비었다면 -> 스택에 있는 값 큐에 삽입
stack만 비었다면 -> pq에 있는 값 큐에 삽입
둘 다 있다면 -> 연산 후 적절한 값 큐에 삽
else -> 현재 진행 중인 과제가 있다면 => 해당 else의 목적은 큐에 등록된 과제 처리 후 삭제
pq가 비었거나 현재 작업을 완료해도 다음작업 시작시간이 안 됐다면 -> result에 결과 추가
아니라면 -> 현재 작업 중인 값 pq에 삽입
import java.util.*;
class Solution {
public String[] solution(String[][] plans) {
PriorityQueue<Task> pq = new PriorityQueue<>((e1, e2) -> e1.start - e2.start);
for(String[] plan : plans){
String[] time = plan[1].split(":");
int hour = Integer.parseInt(time[0]) * 60;
int minute = Integer.parseInt(time[1]);
pq.add(new Task(plan[0], hour + minute, Integer.parseInt(plan[2])));
}
Stack<Task> stack = new Stack<>();
ArrayDeque<Task> q = new ArrayDeque<>();
int now = 0;
int index = 0;
String[] result = new String[plans.length];
while(!pq.isEmpty() || !stack.isEmpty()){
//현재 작업중인 과제가 없다면 -> 현재 과제를 채움
if(q.isEmpty()){
//pq만 없다면
if(pq.isEmpty()){
q.add(stack.pop());
//스택만 없다면
}else if(stack.isEmpty()){
Task t = pq.poll();
now = t.start;
q.add(t);
//pq와 stack 둘다 있다면
}else{
if(now >= pq.peek().start){
q.add(pq.poll());
}else{
q.add(stack.pop());
}
}
}
//현재 작업중인 과제가 있다면 -> 현재 과제를 비움
else{
//pq가 비었거나 현재 작업을 완료해도 다음작업 시작시간이 안된경우
if(pq.isEmpty() || now + q.peek().playtime <= pq.peek().start){
Task t = q.poll();
result[index++] = t.name;
now += t.playtime;
}else{
Task t = q.poll();
t.playtime -= (pq.peek().start - now);
stack.push(t);
now = pq.peek().start;
}
}
}
result[index] = q.poll().name;
return result;
}
static class Task{
String name;
int start, playtime;
public Task(String name, int start, int playtime){
this.name = name;
this.start = start;
this.playtime = playtime;
}
}
}
테스트케이스 4,5,6과 7,8,9에서 문제가 발생한다면 시간 처리에서 오류가 발생한 것이다.
위 코드에서 현재 시간과 과제시작시간, 플레이타임 총 3개를 관리하는데
t.playtime -= (pq.peek().start - now); 에서 현재 시간을 빼는 게 아니라 t.start를 뺀다거나
now += t.playtime; 여기서 now = t.start + t.playtime으로 선언하면 저 부분에서 문제가 발생한다.
'알고리즘' 카테고리의 다른 글
[코드트리 조별과제] 시간복잡도 (0) | 2024.07.27 |
---|---|
[JAVA 자바] 프로그래머스 PCCP 모의고사 3번 유전법칙 (0) | 2023.06.09 |
[JAVA 자바] 백준 2179 (0) | 2023.05.25 |
[프로그래머스] 혼자 놀기의 달인 자바 (0) | 2022.10.13 |
여행경로 자바 (0) | 2022.09.06 |