안녕하세요! 쏘코입니다. 오늘은 재택근무를 마치고 조금 쉬다가 다시 PS문제를 잡아보았습니다.
스택/큐 고득점 Kit의 마지막 문제입니다. 생각보다 재밌는 문제였어요. 딱 40분정도 걸렸습니다.
목차
0. 문제 설명
일반적인 프린터는 인쇄 요청이 들어온 순서대로 인쇄합니다. 그렇기 때문에 중요한 문서가 나중에 인쇄될 수 있습니다. 이런 문제를 보완하기 위해 중요도가 높은 문서를 먼저 인쇄하는 프린터를 개발했습니다. 이 새롭게 개발한 프린터는 아래와 같은 방식으로 인쇄 작업을 수행합니다.
1. 인쇄 대기목록의 가장 앞에 있는 문서(J)를 대기목록에서 꺼냅니다.
2. 나머지 인쇄 대기목록에서 J보다 중요도가 높은 문서가 한 개라도 존재하면 J를 대기목록의 가장 마지막에 넣습니다.
3. 그렇지 않으면 J를 인쇄합니다.
예를 들어, 4개의 문서(A, B, C, D)가 순서대로 인쇄 대기목록에 있고 중요도가 2 1 3 2 라면 C D A B 순으로 인쇄하게 됩니다.
내가 인쇄를 요청한 문서가 몇 번째로 인쇄되는지 알고 싶습니다. 위의 예에서 C는 1번째로, A는 3번째로 인쇄됩니다.
현재 대기목록에 있는 문서의 중요도가 순서대로 담긴 배열 priorities와 내가 인쇄를 요청한 문서가 현재 대기목록의 어떤 위치에 있는지를 알려주는 location이 매개변수로 주어질 때, 내가 인쇄를 요청한 문서가 몇 번째로 인쇄되는지 return 하도록 solution 함수를 작성해주세요.
0.0. 제한사항
- 현재 대기목록에는 1개 이상 100개 이하의 문서가 있습니다.
- 인쇄 작업의 중요도는 1~9로 표현하며 숫자가 클수록 중요하다는 뜻입니다.
- location은 0 이상 (현재 대기목록에 있는 작업 수 - 1) 이하의 값을 가지며 대기목록의 가장 앞에 있으면 0, 두 번째에 있으면 1로 표현합니다.
0.1. 입출력 예
priorities | location | return |
[2, 1, 3, 2] | 2 | 1 |
[1, 1, 9, 1, 1, 1] | 0 | 5 |
0.2. 입출력 예 설명
예제 #1
문제에 나온 예와 같습니다.
예제 #2
6개의 문서(A, B, C, D, E, F)가 인쇄 대기목록에 있고 중요도가 1 1 9 1 1 1 이므로 C D E F A B 순으로 인쇄합니다.
1. 풀이 과정
조금 무식한 방법으로.. 풀었습니다 ㅋㅋㅋㅋㅋㅋ
기본 골격은 pair를 담은 queue에서 max가 아니면 뺐다가 다시 맨 뒤로 넣고 max면 빼서 location값만 출력 순서를 담을 vector에 넣어준 뒤 solution의 파라미터인 location값을 찾아서 +1 해주면 끝이었습니다. (0번째가 아닌 1번째부터 시작이기 때문에 index를 찾은 후에 +1을 해 줬습니다!)
먼저 int형 변수 2개를 저장한 pair를 담은 queue를 만들고, 출력 순서를 담을 vector를 만들어줬습니다.
pair를 담아둘 temp 변수도 미리 만들었고, priorities의 size도 미리 변수처리를 해 뒀습니다.
첫 번째 for문에서는 만들어준 queue에 location과 priority값을 넣어줬습니다.
priorities의 index가 그대로 location의 위치에 들어가면 됐기 때문에 i값을 넣어줬습니다.
while문에서는 만들어준 queue에서 모든 pair를 뺄 때까지 계속 돌리는 것을 조건으로 했습니다.
정수형 변수인 max를 만들고, queue의 size만큼 for문을 돌려서 max값을 찾습니다.
이 과정에서 queue에서는 index를 사용할 수 없기 때문에 빼고 다시 뒤로 넣고를 반복해줍니다.
while문 안에 있는 두 번째 for문에서는 다시 queue의 최대 size만큼 for문을 돌려서 max값을 찾습니다. 최대라고 한 이유는 중간에 max값을 발견하면 그 pair를 빼서 출력 순서를 담을 vector에 넣어주고 for문을 종료하기 때문입니다. for문을 돌리면서 max값이 아닌 값들은 빼고 맨 뒤로 넣어줍니다.
이 과정을 반복해서 while문을 빠져나오면 이제 출력 순서를 담아놓은 vector에서 solution에서 받은 입력값인 location의 위치를 찾아줍시다. vector이기 때문에 index를 사용할 수 있습니다! 찾아서 +1을 해 주면 끝입니다.(사람이 세는 것처럼 1번째부터 시작하기 때문에!!)
2. 소스 코드
#include <string>
#include <vector>
#include <queue>
using namespace std;
int solution(vector<int> priorities, int location) {
int answer = 0;
queue<pair<int,int>> lopi; // location, priority 순으로 들어가는 queue 생성
pair<int, int> temp = make_pair(0,0); // pair 저장용 변수
vector<int> ans; // 출력순서 저장하는 큐 (location만 저장)
int size = priorities.size();
for (int i = 0; i < size; ++i){ // 큐에다가 location, priority값 넣어줌
temp = make_pair(i, priorities[i]); // i는 기존의 location을 넣기 위해서 만들어준 변수
lopi.push(temp);
}
while (!lopi.empty()){
int max = 0;
for (int i = 0; i < lopi.size(); ++i){ // max값 찾기
if ((lopi.front()).second > max) // lopi[i]의 priority값이 더 크면
max = (lopi.front()).second; // max값 새로고침
temp = lopi.front();
lopi.pop();
lopi.push(temp);
}
for (int i = 0; i < lopi.size(); ++i){ // 출력해야 할 문서를 찾으면 큐에서 빼서 ans에 위치값 저장
if((lopi.front()).second == max){
temp = lopi.front();
lopi.pop();
ans.push_back(temp.first);
break; // while문 다시 시작
}
else{
temp = lopi.front();
lopi.pop();
lopi.push(temp);
}
}
}
for (int i = 0; i < ans.size(); ++i){
if(ans[i] == location){
answer = i+1;
break;
}
}
return answer;
}
3. 후기
반신반의했는데, 원하는 대로 알고리즘을 짜서 한방에 맞았을 때의 그 기분은 참 말로 표현할 수가 없습니다.
물론 다른 분들의 풀이를 보니 max_element와 iterator를 사용해서 index만 뽑아내서 푸는 더 좋은 방법이 있었습니다. 이를 통해 아직 내가 iterator와 별로 친해지지 않았구나 하는 자기반성도 하게 되는 좋은 문제였습니다.
출처: 프로그래머스 코딩 테스트 연습, https://programmers.co.kr/learn/challenges
최근댓글