알고리즘
[Javascript] 프로그래머스 - 과제 진행하기
J3SUNG
2025. 2. 26. 22:01
728x90
문제 설명
루는 여러 개의 과제를 수행해야 하며, 다음과 같은 규칙을 따릅니다.
- 과제는 정해진 시작 시각이 되면 시작합니다.
- 새로운 과제를 시작해야 하는 시각이 되면, 진행 중이던 과제는 멈추고 새 과제를 시작합니다.
- 멈춘 과제는 이후 시간이 생기면 다시 진행합니다.
- 멈춰둔 과제가 여러 개라면, 가장 최근에 멈춘 과제부터 진행합니다.
- 과제를 완료한 순서대로 결과를 반환해야 합니다.
제한 사항
- 과제 개수는 3개 이상 1,000개 이하입니다.
- 과제 이름은 알파벳 소문자로 이루어져 있으며, 길이는 2~10자입니다.
- 모든 과제의 시작 시각은 겹치지 않으며, "hh:mm" 형식으로 주어집니다.
- 각 과제의 소요 시간은 1분 이상 100분 이하입니다.
- 주어진 과제 목록은 반드시 시간순으로 정렬되어 있지는 않습니다.
해결 방법
알고리즘: 스택(Stack) 활용
- 시간을 비교하기 쉽게 시각을 분 단위로 변환한 후, 시작 시각 기준으로 정렬합니다.
- 과제 목록을 순회하며
- 이전 과제의 남은 시간이 있다면, 새 과제 시작 전까지 진행합니다.
- 새로운 과제가 시작되면 진행 중이던 과제를 스택에 저장하고 새 과제를 시작합니다.
- 모든 과제를 순회한 후, 스택에 남아 있는 과제를 처리하여 완료 순서를 반환합니다.
시간 복잡도
- O(N log N) (정렬) + O(N) (스택 활용) → O(N log N)
구현 코드
function getTime(time) {
return parseInt(time.slice(0, 2)) * 60 + parseInt(time.slice(3));
}
function solution(plans) {
let answer = [];
plans.sort((a, b) => getTime(a[1]) - getTime(b[1]));
let testStack = [];
let prevTime = 0;
for (const [test, time, duringStr] of plans) {
const curTime = getTime(time);
const during = Number(duringStr);
let remainingTime = curTime - prevTime;
while (remainingTime > 0 && testStack.length > 0) {
const [prevTest, prevDuring] = testStack.pop();
if (prevDuring > remainingTime) {
testStack.push([prevTest, prevDuring - remainingTime]);
break;
}
answer.push(prevTest);
remainingTime -= prevDuring;
}
testStack.push([test, during]);
prevTime = curTime;
}
while (testStack.length > 0) {
answer.push(testStack.pop()[0]);
}
return answer;
}