[큐] 코딩테스트 문제 TIL (요세푸스 문제)- 백준 1158번

말하는 감자·2024년 8월 29일
1
post-thumbnail

안녕하세요!

오늘 문제는 백준 1158번, 요세푸스 문제입니다.

드가자!!


1. 오늘의 학습 키워드

  • 구현
  • 자료 구조

2. 문제: 요세푸스 문제 (1158번)

요세푸스 문제

시간 제한메모리 제한제출정답맞힌 사람정답 비율
2 초256 MB119359600064215249.082%

문제

요세푸스 문제는 다음과 같다.

1번부터 N번까지 N명의 사람이 원을 이루면서 앉아있고, 양의 정수 K(≤ N)가 주어진다. 이제 순서대로 K번째 사람을 제거한다. 한 사람이 제거되면 남은 사람들로 이루어진 원을 따라 이 과정을 계속해 나간다. 이 과정은 N명의 사람이 모두 제거될 때까지 계속된다. 원에서 사람들이 제거되는 순서를 (N, K)-요세푸스 순열이라고 한다. 예를 들어 (7, 3)-요세푸스 순열은 <3, 6, 2, 7, 5, 1, 4>이다.

N과 K가 주어지면 (N, K)-요세푸스 순열을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N과 K가 빈 칸을 사이에 두고 순서대로 주어진다. (1 ≤ K ≤ N ≤ 5,000)

출력

예제와 같이 요세푸스 순열을 출력한다.

예제 입력 1 복사

7 3

예제 출력 1 복사

<3, 6, 2, 7, 5, 1, 4>

출처

  • 문제를 만든 사람: author5

알고리즘 분류


3. 나의 풀이

문제 접근 방식

이 문제는 고전적인 요세푸스 문제로, 사람들이 원을 이루며 앉아 있을 때 K번째 사람을 제거하는 과정을 반복하여 제거된 사람들의 순서를 구하는 문제입니다. 문제의 핵심은 리스트에서 순차적으로 K번째 요소를 제거하는 것입니다.

이 문제는 큐 자료 구조를 사용하면 쉽게 해결할 수 있습니다. 큐는 FIFO(First In, First Out) 특성을 가지며, 요세푸스 문제는 이와 유사한 방식으로 원형 큐에서 순차적으로 사람들을 제거하는 과정과 같습니다. 하지만, 이 문제에서는 실제로 큐를 구현하지 않고 리스트와 인덱스를 활용하여 직접적으로 요소를 제거하는 방식으로 문제를 해결할 수 있습니다.

코드 설명

import sys

N, K = map(int, sys.stdin.readline().split())

a = [i for i in range(1, N+1)]  # 1부터 N까지의 사람들을 리스트로 저장
idx = 0  # 제거할 사람의 인덱스를 가리킬 변수
result = []  # 제거된 사람들의 순서를 저장할 리스트

for _ in range(N):
    idx += K - 1  # 현재 인덱스에서 K번째 사람을 제거하기 위해 K-1을 더함
    if idx >= len(a):  # 인덱스가 리스트의 길이를 초과할 경우 원형으로 순환시키기 위해 모듈러 연산을 사용
        idx %= len(a)

    result.append(str(a.pop(idx)))  # 제거된 사람을 결과 리스트에 추가하고, 리스트에서 제거

# 결과 출력: 리스트의 요소를 ','로 구분하여 출력하고, 앞뒤에 '<', '>'를 추가
print('<' + ', '.join(result) + '>')

코드 동작 방식

  1. 리스트 생성: a = [i for i in range(1, N+1)]를 통해 1부터 N까지의 숫자를 리스트 a에 저장합니다. 이 리스트는 사람들이 원을 이루고 있는 상태를 나타냅니다.
  2. 인덱스 초기화: idx는 제거할 사람의 인덱스를 가리키며, 처음에는 0으로 설정됩니다.
  3. 반복문을 통해 사람 제거:
    • idx += K - 1을 통해 현재 인덱스에서 K번째 위치로 이동합니다.
    • if idx >= len(a) 조건문은 인덱스가 리스트 길이를 초과할 경우, 리스트가 원형처럼 이어지도록 모듈러 연산(%)을 사용하여 인덱스를 조정합니다.
    • result.append(str(a.pop(idx)))는 현재 인덱스에 해당하는 사람을 리스트에서 제거하고, 제거된 사람을 result 리스트에 추가합니다.
  4. 결과 출력: 모든 사람이 제거된 후, result 리스트를 출력합니다. 출력 형식은 문제에서 요구하는 대로 리스트 요소를 ','로 구분하고, 결과를 '<', '>'로 감싸 출력합니다.

이 알고리즘은 O(N)O(N)의 시간 복잡도를 가지며, 리스트의 크기가 줄어들면서 연산이 더 빠르게 수행되기 때문에 효율적입니다. 기본적으로 큐의 개념을 리스트와 인덱스 계산으로 대체하여 문제를 해결한 방식입니다.


마무리

이렇게 해서 요세푸스 문제를 해결했습니다!

계속해서 문제를 풀어나가면서 자료 구조와 알고리즘에 대한 이해를 깊게 해야지!

Let's keep pushing forward! 💪

profile
할 수 있다

0개의 댓글

관련 채용 정보