문제
요세푸스 문제는 다음과 같다.
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>
내가 푼 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken()); //7
int K = Integer.parseInt(st.nextToken()); //3
List<Integer> Ns = new ArrayList<>();
List<Integer> ans = new ArrayList<>();
int idx = 0;
for (int i=0; i<N; i++) {
Ns.add(i+1);
}
for (int i=0; i<N; i++) {
idx += K - 1;
idx %= N - ans.size();
ans.add(Ns.remove(idx));
}
StringBuilder result = new StringBuilder();
result.append("<");
for (int i=0; i<ans.size(); i++) {
result = i != ans.size()-1 ? result.append(ans.get(i) + ", ") : result.append(ans.get(i));
}
result.append(">");
System.out.println(result);
}
}
N의 연속된 자연수의 값을 하나씩 삭제해주면서 반복문을 돌려야하기 때문에 Array가 아닌 List를 사용했다.
한개씩 갯수가 줄어들때마다 요소의 idx가 가리키는 값이 바뀌기 때문에 주의!
7개일때는 2번째 인덱스 삭제 (idx = K-1 = 2)
6개일때는 4번째 인덱스 삭제 (idx = idx + K-1 = 4)
5개일때는 1번째 인덱스 삭제 (idx = idx + K-1 = 6)
4개일때는 2번째 인덱스 삭제 (idx = idx + K-1 = 8)
3개일때는 3번째 인덱스 삭제 (idx = idx + K-1 = 10)
2개일때는 6번째 인덱스 삭제 (idx = idx + K-1 = 12)
1개일때는 14번째 인덱스 삭제 (idx = idx + K-1 = 12)
따라서 삭제할 인덱스는 idx %= N 이다. (N을 이전 idx로 나눈 나머지가됨)
다른사람이 푼 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int K = Integer.parseInt(st.nextToken());
Queue queue = new LinkedList();
StringBuffer sb = new StringBuffer();
sb.append("<");
for (int i=1; i<=N; i++) {
queue.offer(i);
}
while (queue.size() > 1) {
for (int i = 0; i < K; i++) {
if (i == K - 1) {
sb.append(queue.poll() + ", ");
} else {
queue.offer(queue.poll());
}
}
}
sb.append(queue.poll() + ">");
System.out.println(sb);
}
}
연속된 자연수를 Queue에 넣은 다음 queue의 갯수가 1개가 남을때 까지 반복문을 돌려주는데,
이때, K-1 번째 인덱스를 기준으로 그 값을 제거해주고(StringBuffer에 append) 나머지 값은 queue에서 빼서 다시 queue로 넣어주는 방식이다.
'백준 코딩테스트' 카테고리의 다른 글
[백준] 카드2 (2164) - Java (1) | 2023.10.28 |
---|---|
[백준] 괄호 (9012) - Java (3) | 2023.10.28 |
[백준] DNA 비밀번호 (12891) - Java (0) | 2023.08.03 |
[백준] 블로그 (21921) - Java (0) | 2023.08.02 |
[백준] 주몽 (1940) (0) | 2023.08.01 |