Algorithm

[백준] 2531: 회전 초밥 JAVA

하다보면 되겠지 2023. 1. 15. 16:03

접근

이전 20922번과는 달리 k라는 일정한 간격이 정해져 있어서, 상대적으로 투포인터의 느낌이 옅은 것 같은 문제였다. 입력값 저장은 일차원 배열에 하지만 회전 초밥은 시작과 끝이 연결되어 있으므로 left (시작 지점)이 n-1번째까지 오도록 반복하고, right는 n과 같아질 경우 다시 0번째 인덱스로 돌려줬다. 나는 코드에서 d값을 쓰지는 않았다.

 

코드

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 d = Integer.parseInt(st.nextToken());
        int k = Integer.parseInt(st.nextToken());
        int c = Integer.parseInt(st.nextToken());

        int[] arr = new int[n];
        Map<Integer, Integer> map = new HashMap<>();

        for (int i = 0; i < n; i++)
            arr[i] = Integer.parseInt(br.readLine());

        // 처음 k개 초밥 계산
        int cnt = 0;
        for (int i = 0; i < k; i++) {
            map.put(arr[i], map.getOrDefault(arr[i], 0) + 1);
            if (map.get(arr[i]) == 1) cnt++;
        }
        int answer = cnt;

        // 투포인터 적용
        int right = k;
        for (int left = 0; left < n; left++) {
            if(right == n) right = 0;

            map.put(arr[left], map.get(arr[left]) - 1);
            if(map.get(arr[left]) == 0) cnt--;

            map.put(arr[right], map.getOrDefault(arr[right], 0) + 1);
            if(map.get(arr[right]) == 1) cnt++;

            // 쿠폰 번호 확인
            if(map.getOrDefault(c, 0) == 0) answer = Math.max(answer, cnt+1);
            else answer = Math.max(answer, cnt);

            // 포인터 이동
            right++;
        }

        System.out.println(answer);
    }
}