프로그래머스 Java : 과제 진행하기

문제

문제 링크 : https://school.programmers.co.kr/learn/courses/30/lessons/176962

풀이전략

새로운 과제를 시작할 시각이 되었을 때, 기존에 진행 중이던 과제가 있다면 진행 중이던 과제를 멈추고 새로운 과제를 시작합니다.

  • 우선순위는 새로운 과제가 높다.
  • 새로운 과제와 멈춰둔 과제 2가지가 종류의 과제가 존재한다.

hh:mm의 형태로 시간이 주어진다.

  • hh:mm이니까 hh*60 + mm, 즉 모두 분으로 바꾸어서 해결하면 편리함.

멈춰둔 과제가 여러 개일 경우, 가장 최근에 멈춘 과제부터 시작합니다.

  • 새로운 과제는 오름차순 정렬, 멈춰둔 과제는 내림차순 정렬
  • 멈춰둔 과제의 경우 Stack을 사용해도 좋음
  • 멈춰둔 과제는 여러개일 수 있음

코드

import java.util.*;


class Solution {

    static class Assignment{
        String name;
        int start;
        int time;

        public Assignment(String name, String start, String time){
            this.name = name;
            String[] tmpStart = start.split(":");
            this.start = Integer.parseInt(tmpStart[0]) * 60 + Integer.parseInt(tmpStart[1]);
            this.time = Integer.parseInt(time);
        }

        public Assignment(String name, int start, int time){
            this.name = name;
            this.start = start;
            this.time = time;
        }

    }

    public String[] solution(String[][] plans) {
        StringBuilder sb = new StringBuilder("");


		//  PriorityQueue가 2개, new용, old용
		//  new용은 시간순으로 처리 -> 시작하는 시간이 되면 무조건 바꿈

        PriorityQueue<Assignment> newA = new PriorityQueue<>((a1, a2) -> a1.start - a2.start);
        PriorityQueue<Assignment> oldA = new PriorityQueue<>((a1, a2) -> a2.start - a1.start);

        for(int i=0; i<plans.length; i++){
            newA.add(new Assignment(plans[i][0],plans[i][1],plans[i][2]));
        }
        Assignment cur = newA.poll();
        while(!newA.isEmpty() || !oldA.isEmpty()){

			// newA가 empty일 경우
            if(newA.isEmpty()){
                sb.append(cur.name + " ");

                cur = oldA.poll();
                continue;
            }

            Assignment newTop = newA.peek();

			// 현재 과제가 끝난 것이 새로운 과제의 시작일 경우
            if(newTop.start == cur.start + cur.time){
                sb.append(cur.name + " ");
                cur = newA.poll();
            }
			// 현재 과제가 끝나기 전에 새로운 과제의 시작일 경우
            else if(newTop.start < cur.start + cur.time){
                cur.time = cur.start + cur.time - newTop.start;
                cur.start = newTop.start;
                oldA.add(cur);
                cur = newA.poll();
            }
			// 현재 과제가 끝나도, 새로운 과제를 시작할 수가 없는 경우 -> Old과제에서 가져오기
			else {
                sb.append(cur.name + " ");
                if(oldA.isEmpty()){
                    cur = newA.poll();
                } else {
					// 주요부분 : old과제의 시작 시간은 결국 뽑힌 순간의 시간임
                    int curTime = cur.start + cur.time;
                    cur = oldA.poll();
                    cur.start = curTime;
                }
            }
        }
        sb.append(cur.name + " ");
        return sb.toString().split(" ");
    }
}

회고

  • 오랜만에 알고리즘을 풀어서 꽤 오래 걸렸다. Old고제의 시작 시간이 결국 뽑힌 순간의 시간임을 늦게 알게 되었지만, 문제를 풀때 조금 더 집중해야겠다.
  • StirngBuilder로 배열을 만들 수 있는 방법이 있다는 것을 갈게 되었다.

Written by@Gomster
항상 노력하고 나아가는 백엔드 개발자가 되고 싶은 대학생입니다.

GitHub