감자는 아직 꿈을 꾼다.

[백준] 실버 4 요세푸스 본문

코테적 감자/백준

[백준] 실버 4 요세푸스

dreaming-potato 2024. 11. 3. 00:55

알고리즘 : 큐 or 연결리스트

https://www.acmicpc.net/problem/1158

 

 

 

 

 

문제 설명

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

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

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


두 가지의 풀이 방법이 있다.

1. 큐

큐를 사용해서 푸는 것이 제일 연상하기 쉬운 풀이 방법이다.
하지만 메모리와 시간속도 측면에서 보면 연결리스트보단 느리다.

import java.io.*;
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());

        ArrayDeque<Integer> q = new ArrayDeque<>();
        for (int i = 1;i <= n; i++){
            q.addLast(i);
        }
        StringBuilder sb = new StringBuilder();
        sb.append("<");
        for (int i = 0; i < n;i++){
            if (q.size() == 1) break;
            for (int j = 0; j < k-1; j++){
                int temp = q.pollFirst();
                q.addLast(temp);
            }
            sb.append(q.pollFirst() + ", ");
        }
        sb.append(q.pollFirst()+">");

        System.out.println(sb.toString());

    }

}

2. 연결리스트

연결리스트를 사용하면 큐처럼 양쪽 끝의 삽입과 삭제를 계속해서 반복하지 않아도 된다.
인덱스를 사용해서 원형큐의 모듈러 연산을 활용해 인덱스로 임의 접근한다.
모듈러 연산시 리스트의 크기로 연산하는 것이 중요.

import java.io.*;
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());

        List<Integer> list = new ArrayList<>();
        for (int i = 1;i <= n; i++){
            list.add(i);
        }
        StringBuilder sb = new StringBuilder();
        sb.append("<");

        int idx = 0;
        while(list.size() > 1) {
            idx = (idx + (k - 1)) % list.size();
            sb.append(list.remove(idx) + ", ");
        }
        sb.append(list.get(0)+">");

        System.out.println(sb.toString());

    }

}