99클럽 코테 스터디 7일차 TIL / [프로그래머스] 과제 진행하기

전종원·2024년 7월 28일
0

오늘의 학습 키워드


구현

문제


https://school.programmers.co.kr/learn/courses/30/lessons/176962

  • 플랫폼: 프로그래머스
  • 문제명: 과제 진행하기
  • 난이도: Lv2

풀이


import java.util.*;

class Solution {
    public String[] solution(String[][] plans) {
        PriorityQueue<Subject> pQ = input(plans);
        List<String> ansList = proceedSubject(pQ);
        return ansList.stream().toArray(String[]::new);
    }
    
    public PriorityQueue input(String[][] plans) {
        PriorityQueue<Subject> pQ = new PriorityQueue<>();
        
        for(String[] plan : plans) {
            String name = plan[0];
            String startTime = plan[1];
            int remainedMinute = Integer.parseInt(plan[2]);
            
            String[] split = startTime.split(":");
            int hour = Integer.parseInt(split[0]) * 60;
            int minute = Integer.parseInt(split[1]);
            
            pQ.offer(new Subject(name, hour + minute, remainedMinute));
        }
        
        return pQ;
    }
    
    public List proceedSubject(PriorityQueue<Subject> pQ) {
        List<String> ansList = new ArrayList<>();
        Stack<Subject> readyStack = new Stack<>();
        
        readyStack.push(pQ.poll());
        
        while(!pQ.isEmpty()) {
            Subject next = pQ.poll();
            int curTime = readyStack.peek().startTimeByMinute;
            
            while(!readyStack.isEmpty()) {
                Subject cur = readyStack.pop();
                int interval = next.startTimeByMinute - curTime;
                
                // 현재 과제를 끝내고 다음 과제까지 시간이 남는 경우
                if(cur.remainedMinute < interval) {
                    ansList.add(cur.name);
                    curTime += cur.remainedMinute;
                }
                
                // 현재 과제를 끝내고 다음 과제를 바로 시작하는 경우
                else if(cur.remainedMinute == interval) {
                    ansList.add(cur.name);
                    break;
                }
                
                // 현재 과제를 끝내지 못하고 다음 과제를 시작해야 하는 경우
                else {
                    cur.remainedMinute -= interval;
                    System.out.println(cur.name);
                    readyStack.push(cur);
                    break;
                }
            }
            
            readyStack.push(next);
        }
        
        while(!readyStack.isEmpty()) {
            ansList.add(readyStack.pop().name);
        }
        
        return ansList;
    }
    
    public static class Subject implements Comparable<Subject> {
        String name;
        int startTimeByMinute;
        int remainedMinute;
        
        public Subject(String name, int startTimeByMinute, int remainedMinute) {
            this.name = name;
            this.startTimeByMinute = startTimeByMinute;
            this.remainedMinute = remainedMinute;
        }
        
        @Override
        public int compareTo(Subject s) {
            return this.startTimeByMinute - s.startTimeByMinute;
        }
    }
}

접근

  • hh:mm으로 들어오는 시간은 모두 분 단위로 환산하여 표현했습니다.
  • 과제에 대한 정보를 관리하고, 시작 시간 순으로 정렬하기 위해 Subject 클래스를 정의했습니다.
  • 구현 시에 발생할 수 있는 세 가지 케이스를 if문으로 분기하여 풀이했습니다.
    1. 현재 과제를 끝내고 다음 과제까지 시간이 남는 경우

      → 대기 스택에 위치한 과제 수행

    2. 현재 과제를 끝내고 다음 과제를 바로 시작하는 경우

    3. 현재 과제를 끝내지 못하고 다음 과제를 시작해야 하는 경우

      → 현재 과제의 남은 시간을 갱신하고 다시 대기 스택에 삽입

  • 마지막 과제까지 읽어서 다음 과제가 존재하지 않게 되면, 시간과 관계없이 대기 스택에 쌓인 순서대로 과제가 수행되므로 pop하면서 순서를 저장합니다.

소요 시간

1시간

회고


간단한 문제처럼 보여서 흐름에 따라 바로 구현 들어갔다가 코드 퀄리티가 많이 떨어짐을 느껴 뒤늦게 리팩토링을 진행했습니다. 생각보다 시간이 오래 걸렸네요. 😅

0개의 댓글