본문 바로가기

프로그래머스

과제 진행하기 <JAVA> - Level2

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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

전형적인 구현문제 처럼 보였다.

 

주어진 Plans 배열은 [name, start, playtime] 이였고 문제를 보고

1.start 기준으로 오름차순 정렬을 하여 우선순위 큐에 넣는다.

2.새로운 과제가 있다면 해당 과제를 시작한다. 만약 현재시간 (now) + 새로운 과제 소요 시간이 다음 시작될 과제 start 보다 크다면? 

중간에 과제를 멈추고 다음 과제를 진행해야한다.

하다만 과제를 stack 에 넣어주는데 주의할 점 -> 하다만 과제 playtime - (다음 과제 시작시간 - 하다만 과제 시작시간) 을 초기화해서 push 를 해야함

3.과제를 멈추지 않고 끝낼 수 있다면? -> answer 에 과제의 이름을 삽입

-현재 시간에 곧 바로 시작할 다음 과제가 있다면 해당 과제를 시작

-현재 시각에 새로 시작할 과제가 없고 , 하다만 과제가 있다면 가장 최근에 멈춘 과제를 다시 시작함

-멈춰둔 과제도 없고, 일정 시간 후에 시작할 과제가 존재한다면? 해당 과제를 시작한다. 이때 과제 시작시간을 초기화 해

-위의 모든 과정이 아니라면 break!

 

코드

import java.util.*;

class Solution {
     class Subject implements Comparable<Subject> {
        String name;
        int start;
        int playtime;
        
        public Subject(String name,int start,int playtime) {
            this.name = name;
            this.start = start;
            this.playtime = playtime;
        }
        
        @Override
        public int compareTo(Subject sub) {
            return this.start - sub.start;
        }
    }
    public String[] solution(String[][] plans) {
        String[] answer = new String[plans.length];
        
        PriorityQueue<Subject> pq = new PriorityQueue<>((o1,o2) -> (o1.start - o2.start));
        for(String[] plan : plans) {
            pq.add(new Subject(plan[0],convertStringToInt(plan[1]), Integer.parseInt(plan[2])));
        }
        
        Subject sub = pq.poll(); //music 꺼내
        int now = sub.start;
        int idx = 0;
        Stack<Subject> tmpStop = new Stack<>(); //잠시 멈춰둔 과제를 집어넣는 곳
        while(true) {
            if(!pq.isEmpty() && now + sub.playtime > pq.peek().start) {
                //진행중이던 과제 중지
                tmpStop.push(new Subject(sub.name, sub.start, sub.playtime - (pq.peek().start - now)));
                
                now = pq.peek().start; //새로운 시작시간을 다음 과제 시작시간으로 초기화
                sub = pq.poll(); //새로운 과제 시작
            } else {
                //과제 끝낼 경우?
                answer[idx++] = sub.name;
                now += sub.playtime;
                
                if(!pq.isEmpty() && now == pq.peek().start) {
                    sub = pq.poll();
                } else if(!tmpStop.isEmpty()) {
                    sub = tmpStop.pop();
                } else if(!pq.isEmpty()) {
                    sub = pq.poll();
                    now = sub.start;
                } else {
                    break;
                }
            }
        }
        return answer;
    }
    
    private static int convertStringToInt(String time) {
        String[] times = time.split(":");
        return Integer.parseInt(times[0]) * 60 + Integer.parseInt(times[1]);
    }
}