문제 풀이

LeetCode 1340. Jump Game V

khj20006 2026. 5. 24. 21:51
반응형

문제

정수 배열 $arr$과 $1$ 이상의 정수 $d$가 주어진다.

인덱스 $i$에서 아래 조건을 만족시키면 인덱스 $j$로 점프할 수 있다.

  • $arr[j] < arr[i]$
  • $\max(i-d, 0) \le j \le \min(i+d, \texttt{arr.length})$
  • $\min(i, j) < k < \max(i, j)$인 모든 $k$에 대해, $arr[k] < arr[i]$

풀이

인덱스 $i$로 점프할 수 있는 조건을 해석하면 다음과 같다.

  • 인덱스 $i$의 양쪽으로, 거리 $d$ 이하의 $arr[i]$보다 큰 가장 가까운 원소


거리 조건만 빠지면, 스택을 응용하는 문제로 변한다.

즉, 점프를 통해 인덱스 $i$를 방문할 수 있는 곳은 좌우 각각 한 군데로 정해진다.

가장 가까운 원소가 아니더라도 점프를 할 수 있지만, 그 경우에는 항상 최적이 아니다.


간단한 반례를 들면, $i < j < k$이고 $arr[i] < arr[j] < arr[k]$라고 가정하자.
거리 조건을 모두 만족한다면, $k$에서 $i$로 바로 점프할 수 있지만 $j$를 항상 거쳐 가는 것이 더 좋다.


스택을 사용해서 각 인덱스마다 양쪽으로 점프할 수 있는 곳을 미리 구해두고,

원소가 큰 순서대로 방문하며 dp를 돌린다.

코드

class Solution {

    public int maxJumps(int[] arr, int d) {
        int N = arr.length;
        int[] left = new int[N];
        int[] right = new int[N];

        Stack<Integer> stack = new Stack<>();
        Arrays.fill(left, -1);
        for(int i=0;i<N;i++) {
            while(!stack.isEmpty() && arr[stack.peek()] < arr[i]) {
                int idx = stack.pop();
                if(i - idx <= d) {
                    left[idx] = i;
                }
            }
            stack.push(i);
        }

        while(!stack.isEmpty()) stack.pop();
        Arrays.fill(right, -1);
        for(int i=N-1;i>=0;i--) {
            while(!stack.isEmpty() && arr[stack.peek()] < arr[i]) {
                int idx = stack.pop();
                if(idx - i <= d) {
                    right[idx] = i;
                }
            }
            stack.push(i);
        }

        int[] dp = new int[N];
        Arrays.fill(dp, 1);
        int[][] infos = new int[N][];
        for(int i=0;i<N;i++) {
            infos[i] = new int[]{arr[i], i};
        }

        Arrays.sort(infos, (a,b) -> b[0]-a[0]);
        int answer = 1;
        for(int[] info : infos) {
            int idx = info[1];

            if(left[idx] != -1) dp[idx] = Math.max(dp[idx], dp[left[idx]] + 1);
            if(right[idx] != -1) dp[idx] = Math.max(dp[idx], dp[right[idx]] + 1);
            answer = Math.max(answer, dp[idx]);
        }

        return answer;
    }
}
반응형