[BOJ] 1966. 프린터 큐

Jimeaning·2023년 4월 29일
1

코딩테스트

목록 보기
85/143

Python3

문제

https://www.acmicpc.net/problem/1966

키워드

문제 풀이

문제 요구사항

  • 현재 Queue의 가장 앞에 있는 문서의 ‘중요도’를 확인한다.
  • 나머지 문서들 중 현재 문서보다 중요도가 높은 문서가 하나라도 있다면, 이 문서를 인쇄하지 않고 Queue의 가장 뒤에 재배치 한다. 그렇지 않다면 바로 인쇄를 한다.
  • 현재 Queue에 있는 문서의 수와 중요도가 주어졌을 때, 어떤 한 문서가 몇 번째로 인쇄되는지 알아내는 문제이다.
  • 문서의 개수 N(1 ≤ N ≤ 100)
  • 몇 번째로 인쇄되었는지 궁금한 문서가 현재 Queue에서 몇 번째에 놓여 있는지를 나타내는 정수 M(0 ≤ M < N). 이때 맨 왼쪽은 0번 째이다.
  • N개 문서의 중요도는 1 이상 9 이하의 정수이고, 중요도가 같은 문서가 여러 개 있을 수도 있다.

변수 및 함수 설명

  • num: 테스트 케이스의 개수
  • n: 문서의 개수 (1 ≤ N ≤ 100)
  • m: 몇 번째로 인쇄되었는지 궁금한 문서 (0 ≤ M < N)
  • que: 각 문서의 중요도 리스트
  • cnt: 몇 번째로 m이 인쇄되는지 카운트하는 변수

풀이

m이 큐에서 몇 번째로 빠져 나갔는지를 알면 되는 문제이다.


(입력 및 선언)
  • 테스트 케이스 num과 n, m, que가 주어진다.
  • cnt는 테스트 케이스마다 초기화되어야 하므로 반복문 안에 써준다.

(반복문)

  • m이 -1이라면 이미 큐를 빠져 나온 것이다.
  • 만약 큐의 첫 번째 값이 제일 크면, 그 값을 삭제한다.
  • m은 한 칸 앞을 가리키도록 하고, 빠져 나갔으니 cnt는 1을 증가시킨다.

    remove() 함수
    remove() 함수는 pop()과 달리 인덱스를 지정하여 해당하는 값을 삭제한다.

    사용 방법
    리스트.remove(삭제하고 싶은 인덱스)
    a = [1, 2, 3, 4]
    > a.remove(a[1])
    a = [1, 3, 4]

  • 만약 큐의 첫 번째 값이 제일 크지 않으면, que의 첫 번째 원소를 que에 맨 뒤에 넣는다. (작은 수를 뒤로 보내기 위함이다)
    - 그리고 첫 번째 원소를 삭제한다.
    - 이때, 만약 m이 0이라면 해당 수가 뒤로 간 것처럼 m도 맨 뒤를 가리키게 한다. 즉, m은 (큐의 총 길이 - 1)이다.
    - m이 0이 아니면, 그 앞에 있는 값을 가리키도록 한다.

최종 코드

num = int(input())

for _ in range(num):
    n, m = map(int, input().split())
    que = list(map(int, input().split()))
    cnt = 0
    
    while (m != -1):
        if que[0] == max(que):
            que.remove(que[0])
            m -= 1
            cnt += 1
        else:
            que.append(que[0])
            que.remove(que[0])
            
            if m == 0:
                m = len(que) - 1
            else:
                m -= 1
    
    print(cnt)

피드백

(추가 23.5.1)

  • 큐의 popleft() 역할을 list의 remove()메서드를 사용했는데, 현재 문제에서는 '앞에서 빼는 작업'이 '단순히 삭제하는 작업' 보다 조금 더 맞는 것 같다.
  • 만약 문서의 갯수가 100만개라면 맨앞의 요소를 삭제할 때마다 O(100만-1)의 시간이 소요된다!

deque의 시간 복잡도

deque의 popleft()를 사용하면 시간복잡도를 O(1)로 줄일 수 있다.
deque는 스택과 큐의 기능을 모두 가진 객체로써 출입구를 양쪽에 가지고 있다. 따라서 스택처럼 써도 되고, 큐처럼 써도 된다.

from collections import deque

num = int(input())

for _ in range(num):
    n, m = map(int, input().split())
    deq = deque(list(map(int, input().split())))
    cnt = 0
    
    while (m != -1):
        if deq[0] == max(deq):
            deq.popleft()
            m -= 1
            cnt += 1
        else:
            deq.append(deq.popleft())
            
            if m == 0:
                m = len(deq) - 1
            else:
                m -= 1
                
    print(cnt)
profile
I mean

0개의 댓글