-
[백준 BOJ] 1158번 요세푸스 문제 (파이썬 Python)코딩/알고리즘 - 백준 2022. 8. 8. 16:23
문제 설명
1번부터 N번까지 N명의 사람이 원을 이루면서 앉아있고, 양의 정수 K (≤ N)가 주어진다.
이제 순서대로 K번째 사람을 제거한다.
한 사람이 제거되면 남은 사람들로 이루어진 원을 따라 이 과정을 계속해 나간다. 이 과정은 N명의 사람이 모두 제거될 때까지 계속된다.
원에서 사람들이 제거되는 순서를 (N, K)-요세푸스 순열이라고 한다.
예를 들어 (7, 3)-요세푸스 순열은 <3, 6, 2, 7, 5, 1, 4>이다.
N과 K가 주어지면 (N, K)-요세푸스 순열을 구하는 프로그램을 작성하시오.
예제 입력1
7 3
코드 및 풀이
처음에는 리스트를 이용하여 풀이를 진행했다. (아래 코드)
리스트는 더 오래걸린다는 것을 알고 있었지만
단순히 양쪽 끝 인덱스만 사용하기 때문에 혹시나 괜찮지 않을까라고 생각하였지만
시간 초과가 발생했다.
import sys input = sys.stdin.readline n, k = map(int, input().split()) arr = [i+1 for i in range(n)] ans = [] while arr: for i in range(k-1): arr.append(arr[0]) del arr[0] ans.append(arr[0]) del arr[0] print("<", end = '') print(*ans, sep = ', ', end = '') print(">") # time over
정답 코드
import sys from collections import deque input = sys.stdin.readline n, k = map(int, input().split()) people = [i+1 for i in range(n)] people = deque(people) result = [] while people: people.rotate(-(k-1)) result.append(people.popleft()) print(str(result).replace('[', '<').replace(']', '>'))
deque 모듈을 사용한 정답코드이다.
먼저 주어진 n까지의 수열을 만들어 준 뒤, deque으로 바꿔준다.
people = [1, 2, 3, 4, 5, 6, 7] << deque
reotate()는 덱을 주어진 수만큼 회전하는 함수이다.
양수면 오른쪽으로, 음수이면 왼쪽으로 회전시킨다.
주어진 수가 3이기 때문에(예제 1) 하나 적은 2만큼 회전 시킨 후
해당 숫자를 뽑아 정답 배열에 추가한다.
[1, 2, 3, 4, 5, 6, 7] (2회 회전)>> [3, 4, 5, 6, 7, 1, 2]
(pop)>> people = [4, 5, 6, 7, 1, 2], result = [3]
해당 과정을 원래 수열이 빌 때까지 반복한다.
출력은 리스트(덱)를 문자열로 바꾼 후
replace 함수를 이용해 문제에서 요구하는 형식으로 바꿔준다.
다른 표현
import sys from collections import deque input = sys.stdin.readline n, k = map(int, input().split()) people = deque() for i in range(1, n+1): people.append(i) result = [] while people: for i in range(k-1): people.append(people.popleft()) # people.rotate(-1) print("<", end = '') print(*ans, sep = ', ', end = '') print(">") # print(str(result).replace('[', '<').replace(']', '>'))
풀이 방식을 같이 하는 다른 표현도 가능하다.
rerotate 대신 pop과 append를 사용하고,
print 방식도 위와 같이 바꿔볼 수 있다.
print문 안의 리스트 앞에 * (Asterisk)를 써주면 리스트를 한 줄로 출력할 수 있게 해준다. (list unpacking)
다른 풀이 (deque 모듈 사용 x)
import sys input = sys.stdin.readline n, k = map(int, input().split()) arr = [i for i in range(1,n+1)] ans = [] num = 0 for i in range(n): num+=(k-1) if num >= len(arr): num %= len(arr) ans.append(str(arr[num])) arr.pop(num) print("<",', '.join(ans),">", sep="")
deque 모듈을 사용하지 않고도 가능하다.
기존 배열을 삭제(pop), 정답 배열을 추가하는 과정에서
num 변수를 선언해 인덱스로 접근한다.
num이 배열보다 커질 경우 나머지 연산 (% )을 이용해
num을 수정해 준다.
출력 과정에서 join 함수를 사용하기 때문에
정답 리스트(ans)에 원소를 추가하는 과정에서 str()을 이용해
문자열로 바꿔서 추가한다.
참고) 덱과 리스트의 시간 복잡도 비교
리스트 덱 시간 복잡도 사진1 (아래 왼쪽) 사진2 (아래 오른쪽) 리스트의 시간 복잡도(왼쪽) 덱의 시간 복잡도(오른쪽) 참조 및 출처
모듈 이용 x: https://imzzan.tistory.com/2
리스트와 덱의 시간 복잡도: https://wellsw.tistory.com/122
문제 출처: https://www.acmicpc.net/problem/1158
1158번: 요세푸스 문제
첫째 줄에 N과 K가 빈 칸을 사이에 두고 순서대로 주어진다. (1 ≤ K ≤ N ≤ 5,000)
www.acmicpc.net
'코딩 > 알고리즘 - 백준' 카테고리의 다른 글
[백준 BOJ] 7562번 나이트의 이동 (파이썬 Python) (0) 2025.03.17 [백준 BOJ] 1260번 DFS와 BFS (파이썬 Python) (0) 2023.05.30 [백준 BOJ] 17298번 오큰수 (파이썬 Python) (0) 2022.09.06 [백준 BOJ] 1406번 에디터 (파이썬 Python) (0) 2022.07.29 [백준 BOJ] 1874번 스택 수열 (파이썬 Python) (0) 2022.07.18