알고리즘 공부

프로그래머스 스택/큐 : [프린터] JAVA 풀이

개발자가 말대꾸? 2022. 5. 2. 11:28

https://programmers.co.kr/learn/courses/30/lessons/42587?language=java 

 

코딩테스트 연습 - 프린터

일반적인 프린터는 인쇄 요청이 들어온 순서대로 인쇄합니다. 그렇기 때문에 중요한 문서가 나중에 인쇄될 수 있습니다. 이런 문제를 보완하기 위해 중요도가 높은 문서를 먼저 인쇄하는 프린

programmers.co.kr

 

 

문제 설명

프린터를 우선순위대로 출력을 할때 내가 원하는 출력물이 몇번째로 출력되는지 구하는 문제입니다.

매개변수로는 우선순위인 int[] pripriorities와 내가 원하는 출력물의 인덱스 location이 주어집니다.

 

1. 인쇄 대기목록의 가장 앞에 있는 문서(J)를 대기목록에서 꺼냅니다.
2. 나머지 인쇄 대기목록에서 J보다 중요도가 높은 문서가 한 개라도 존재하면 J를 대기목록의 가장 마지막에 넣습니다.
3. 그렇지 않으면 J를 인쇄합니다.

 

예시

int[] priorties = {2,1,3,2}
int location = 2

내가 원하는 출력물은 배열의 두번째 인덱스인 "3"입니다.

현재 출력 대기: {2,1,3,2}

현재 출력하려는 2보다 큰 수가 뒤에 있기 때문에 2를 맨 뒤로 보냅니다.  {1,3,2,2}

현재 출력하려는 1보다 큰 수가 뒤에 있기 때문에 1를 맨 뒤로 보냅니다. {3,2,2,1}

현재 출력하려는 3보다 큰 수가 없기 때문에 3을 출력합니다.  ( 첫 번째 출력 ) ( 내가 원하는 출력 물 )

내가 원하는 출력물은 첫 번째로 출력되었으므로 1을 리턴합니다. 

 

 

생각해야 되는 문제

int[] priorties = {1, 1, 9, 1, 1, 1}
int location = 0

내가 출력하고 싶은 프린트는 0번째 인덱스의 "1"입니다. 

하지만 1보다 더 중요한 9가 있기 때문에 맨 뒤로 보냅니다.  {1 , 9, 1, 1, 1, "1" }  "1"은 내가 원하는 출력물입니다.

마찬가지로 1을 맨뒤로 보내줍니다. { 9, 1, 1, 1, "1" , 1 } 

9를 출력합니다. {1, 1, 1, 1, 1, "1" , 1}

이제 1이란 숫자를 뽑을 차례지만, 내가 원하는 출력물은 아닙니다. 

결국 내가 원하는 프린트는 5번째로 출력됩니다.

 

 

나의 풀이

저는 우선 예시와 같이 1과 내가 원하는 출력물 "1"을 구분하기 위해서 class를 만들었습니다. 

먼저 나오지만, 우선순위가 낮은 출력을 뒤로 보내야 함으로 효율적으로 코드를 짜기 위해 덱큐를 사용했습니다.
class El{
    public static int id = 0;

    public int number;
    public int number_id;

    El(int number) {
        id++;
        this.number = number;
        this.number_id  = id;
    }

    public int getNumber(){
        return number;
    }

    public int getNumber_id(){
        return number_id;
    }
}

 

El 클래스는 나의 우선순위: number와 고유한 id를 가지고 있습니다.

생성자에 static int id 를 하나씩 늘려줌으로 각 프린트 물은 서로 다른 id를 가집니다.

 

 

 

 

전체 코드

import java.util.ArrayDeque;
import java.util.Queue;

class El{
    public static int id = 0;

    public int number;
    public int number_id;

    El(int number) {
        id++;
        this.number = number;
        this.number_id  = id;
    }

    public int getNumber(){
        return number;
    }

    public int getNumber_id(){
        return number_id;
    }

}

class Solution {
    public int solution(int[] priorities, int location) {

        int day = 0;

        El target = new El(priorities[location]);

        Queue<El> deque = new ArrayDeque<>();


        for(int i = 0 ; i < priorities.length; i++){
            if(i == location) deque.offer(target);
            else deque.offer(new El(priorities[i]));
        }

        
        while (!deque.isEmpty()) {
            El left = deque.poll();

            if (deque.stream().allMatch((right) -> right.getNumber() <= left.getNumber())) {
                if (left.getNumber_id() == target.getNumber_id()) {
                    return day + 1;
                } else {
                    day++;
                }
            } else {
                deque.offer(left);
            }

        }
        return day + 1;
    }
}
큐가 비어있으면 안됨으로 while의 범위는 큐가 비어있지 않을때까지 입니다.

큐에서 El을 하나 꺼냅니다. 


큐를 순회하면서 El의 우선순위보다 중요한 El이 있는지 확인합니다.

El이 가장 중요한 우선순위라면 El의 id를 비교해서 내가 원하는 출력물인지 확인합니다.

내가 원하는 출력물이 아니라면 우선순위가 높으므로 출력합니다. ( 출력이 나왔으므로 answer를 한개 늘립니다. )

만약 우선순위가 낮다면 맨뒤로 인자를 넣어줍니다. 

출력의 갯수는 한개부터 출력하기 때문에 day + 1을 리턴합니다. 

 

 

 

 

효율성 테스트도 괜찮고 Class를 썻으니 나름대로 Java스러운 코드인것 같습니다.