문제
시간 제한 : 2 초, 메모리 제한 : 512 MB
요세푸스 문제는 다음과 같다.
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 ≤ 1,000)
출력
예제와 같이 요세푸스 순열을 출력한다.
입출력 예
제출 코드
from collections import deque
n, k = map(int, input().split())
d = deque([i for i in range(1, n+1)])
lst = []
while d:
d.rotate(-(k-1))
lst.append(d.popleft())
print('<', end = '')
for i in range(len(lst)):
if i != len(lst)-1:
print("%d, " %lst[i], end = '')
else:
print("%d>" %lst[i])
문제의 핵심
# 1
클래스 deque 안의 rotate를 사용하면 deque type으로 구현된 연결 리스트를 회전시킬 수 있다. rotate의 시간 복잡도가 O(k)라고 하는데, 이게 정확히는 d.append(d.popleft())으로 구현되는 것이고 결국엔 Big-O가 상수라 효율적이라고 생각했다. 핵심은 rotate와 같은 방식을 구현할 거라면 클래스를 import를 하든 본인이 직접 구현하든 연결 리스트로 구현해야 한다는 것이다. 그래야 popleft를 할 때 시간 복잡도를 효율적으로 만들 수 있기 때문이다.
collections의 deque는 아주 좋은 클래스니까 꼭 알아두자. rotate( ) 함수에 관한 document는 [여기]로 이동하여 볼 수 있다.
라인 별 풀이
(1) line 3, 4
사람 수와 제거될 간격을 n과 k에 할당하고, 연결 리스트를 선언하며 1부터 n까지 초기화한다.
(2) line 5
제거되는 사람들을 순서대로 담을 리스트를 선언한다.
(3) line 7 ~ 9
연결 리스트를 k만큼이 아닌 k-1 만큼 왼쪽으로 로테이션하는 이유는 직접 그려보면 간단하다. 입출력 예시에서는 k가 3이었는데 맨 처음 제거될 사람이 3번이므로 2만큼 왼쪽 로테이션 시켜서 [3, 4, 5, 6, 7, 1, 2] 로 만든다. 그리고 3을 제거하면 [4, 5, 6, 7, 1, 2]가 된다. 여기서 또 왼쪽으로 2만큼 로테이션 시키면 [6, 7, 1, 2, 4, 5]가 된다. 이렇듯, 제거한 사람의 수까지 고려하여 k-1만큼 왼쪽으로 로테이션 시켜야 한다.
그 과정을 연결 리스트 내 사람들이 모두 제거될 때까지 반복한다.
(4) line 11 ~ 16
문제에서 요구하는 출력 형태로 답을 출력한다.
'PS > 백준' 카테고리의 다른 글
[백준 알고리즘][파이썬/Python] 11279번: 최대 힙 (1) | 2020.06.28 |
---|---|
[백준 알고리즘][파이썬/Python] 7568번: 덩치 (2) | 2020.06.22 |
[백준 알고리즘][파이썬/Python] 11723번: 집합 (1) | 2020.06.21 |
[백준 알고리즘][파이썬/Python] 1748번: 수 이어 쓰기 1 (0) | 2020.04.18 |
[백준 알고리즘][파이썬/Python] 1764번: 듣보잡 (0) | 2020.04.17 |