[프로그래머스] 징검다리 건너기 - JAVA

https://school.programmers.co.kr/learn/courses/30/lessons/64062

풀이

[2, 4, 5, 3, 2, 1, 4, 2, 5, 1]

위과 같은 배열으로 징검다리들의 숫자가 입력으로 들어온다.

디딤돌을 밟을때마다 숫자가 1씩 줄어들고, 0인 돌이 있다면 안뛰고 건너뛸 수 있다.

하지만, 입력으로 k가 주어지는데 한번에 k개의 돌만 건너뛸 수 있다.

예를 들어, [5, 3, 2, 1, 4] 이러한 배치를 하고있다면

3명이 돌을 건너간 후의 상태는 [2, 0, 0, 0, 1]이 된다.

k가 3일 때, 2인 돌에서 1인 돌로 뛰려면 4칸을 뛰어야하기 때문에 이는 불가능하다.

즉, 건널 수 있는 최대 인원 수는 3명이 된다.

k개씩 구간을 나눠 그 중 최댓값이 그 구간을 건널 수 있는 최대 인원 수가 된다.

일정 구간에서 최댓값을 찾아야하기때문에 세그먼트트리를 적용했다.

k개의 구간을 보면서 그 중 최댓값을 찾고, 그 최댓값들 중 가장 작은 값이 전체 구간에서 건널 수 있는 최대 인원 수가 된다.

세그먼트 트리를 이용해서 풀었지만 다른 풀이들을 찾아보니 이분탐색으로 푼 사람들이 대부분이었다.


메모리: 63.8MB

시간: 43.90ms

언어: Java 11

코드

import java.util.*;

class Solution {
    static class SegmentTree {
        int[] tree;
        int treeSize;

        public SegmentTree(int arrSize) {
            int height = (int) Math.ceil(Math.log(arrSize) / Math.log(2));
            this.treeSize = (int) Math.pow(2, height + 1);
            tree = new int[treeSize];
        }

        public int init(int[] arr, int node, int start, int end) {
            if(start == end) {
                return tree[node] = arr[start - 1];
            } else {
                return tree[node] = Math.max(init(arr, node * 2, start, (start + end) / 2), init(arr, node * 2 + 1, (start + end) / 2 + 1, end));
            }
        }

        public int maxValue(int node, int start, int end, int left, int right) {
            if(left > end || right < start) {
                return 0;
            }

            if(left <= start && end <= right) {
                return tree[node];
            }

            return Math.max(maxValue(node * 2, start, (start + end) / 2, left, right), maxValue(node * 2 + 1, (start + end) / 2 + 1, end, left, right));
        }
    }

    public int solution(int[] stones, int k) {
        int len = stones.length;
        SegmentTree seg = new SegmentTree(len);
        seg.init(stones, 1, 1, len);

        int answer = 200_000_001;
        for(int i = 1; i <= len + 1 - k; i++) {
            answer = Math.min(seg.maxValue(1, 1, len, i, i + k - 1), answer);
        }

        return answer;
    }
}