2026년 2월 23일

[백준] 회전하는 큐 (Python)

 

문제 설명

  • 순환 큐에서 원하는 원소가 앞에 올 때까지 왼쪽/오른쪽 중 더 적게 움직이는 방향으로 회전시키는 과정을 반복해, 그 회전 횟수의 총합을 구하는 문제
 

예제 입력/출력

  • 입력1
    • 10 3 1 2 3
  • 출력1
    • 0
 

제약 조건

  • targets는 1부터 N까지의 서로 다른 정수
 

문제 풀이

  • 이 문제의 핵심은 “원형 구조에서 특정 원소(target)를 맨 앞으로 가져오는 최소 이동 횟수를 반복적으로 구하는 문제” 이다.
  • 여기서 target이란 이번 단계에서 반드시 꺼내야 하는 목표 원소를 의미한다.
 

1️⃣ 초기 상태

  • 1부터 N까지의 원소가 순서대로 들어있는 원형 구조를 만든다.
  • 목표는 주어진 순서대로 원소를 제거하는 것이다.
  • 비용은 회전 연산(왼쪽/오른쪽)만 계산하고, 맨 앞 원소를 제거하는 연산은 비용에 포함되지 않는다.
 

2️⃣ 각 원소를 꺼내는 전략

  • 각 target에 대해 다음 과정을 반복한다.
  1. 현재 위치 파악
      • 현재 원형 구조에서 target이 맨 앞(인덱스 0)에서 몇 칸 떨어져 있는지 파악한다.
      • 이 값을 idx라고 하자.
  1. 두 방향 중 선택
      • 원형 구조이기 때문에 두 가지 이동 방법이 존재한다.
          1. 왼쪽으로 이동한다.
          1. 오른쪽으로 이동한다.
      • 필요한 이동 횟수는 다음과 같다.
        • 왼쪽 이동 비용 = idx
        • 오른쪽 이동 비용 = len(q) - idx
  1. 최소 비용 선택 (그리디)
      • 두 이동 비용 중 더 적은 방향으로 회전한다.
      • 해당 이동 비용을 누적한다.
  1. target 제거
      • target이 맨 앞에 오면 제거한다.
      • 이 연산은 비용에 포함되지 않는다.
      • 그리고 다음 target으로 넘어가 위 과정을 반복한다.
 

3️⃣ 핵심 정리

이 문제는 다음 과정을 반복하는 시뮬레이션 문제다.
  1. 목표 원소(target)의 현재 위치 계산
  1. 원형 거리의 최소값 선택
  1. 회전 후 제거
  1. 누적 비용 계산
 

풀이 코드

from collections import deque import sys def sys_input() -> str: return sys.stdin.readline().rstrip() def solve(n: int, targets: list[int]) -> int: q = deque(range(1, n + 1)) min_count = 0 for t in targets: idx = q.index(t) if idx <= len(q) - idx: q.rotate(-idx) min_count += idx else: q.rotate(len(q) - idx) min_count += len(q) - idx q.popleft() return min_count def main() -> None: N, _ = map(int, sys_input().split()) targets = list(map(int, sys_input().split())) answer: int = solve(N, targets) print(answer) if __name__ == "__main__": main()

참고

  • deque.rotate(k)
    • k > 0 → 오른쪽 회전
    • k < 0 → 왼쪽 회전
  • 위 코드는 아래 코드와 동일한 역할을 한다.
    • # 왼쪽 회전 for _ in range(idx): q.append(q.popleft()) # 오른쪽 회전 for _ in range(idx): q.appendleft(q.pop())