1642. Furthest Building You Can Reach

2024년 2월 17일 작성

LeetcodeGreedyPriority Queue

https://leetcode.com/problems/furthest-building-you-can-reach/description/?envType=daily-question&envId=2024-02-17

저번에 CTCI 읽으면서 일단, 알고리즘 풀때 인간이 문제를 푸는 방식으로 생각해보라고 해서 문제 읽자마자 그냥 떠오르는 방법으로 써봤다.

import java.lang.Math;
 
class Solution {
    private int[] h;
    private int buildingCnt;
    public int furthestBuilding(int[] heights, int bricks, int ladders) {
        h = heights;
        buildingCnt = heights.length;
        return rec(0, bricks, ladders);
    }
 
    private int rec(int i, int bricks, int ladders) {
        if (i == buildingCnt-1) {
            return 0;
        }
        int diff = h[i+1] - h[i];
        if (diff <= 0) {
            return 1 + rec(i+1, bricks, ladders);
        }
        int byLadder = ladders > 0 ? rec(i+1, bricks, ladders - 1) + 1 : 0;
        int byBricks = bricks - diff >= 0 ? hi(i+1, bricks-diff, ladders) + 1 : 0;
 
        return Math.max(byLadder, byBricks);
    }
}

테스트케이스는 모두 통과해서 제출해봤더니,
11/78 개의 문제만 통과하고 Time Limit Exceeded가 떴다.

한 십분 생각했는데 방법이 아예 생각도 안나서 지피티에게 힌트를 달라고 했더니
Priority Queue를 사용해보라고 했다. 물어보지도 않았는데 정답 코드를 줘서 당황했지만
이해에는 도움이 되었다; (그래도 양심껏 코드는 베끼지 않았다.)

코드를 보니, 우선순위큐를 사용하는 이유가 사다리를 쓸지, 벽돌을 쓸지 선택하는 것을 미루기 위해서였다.
위에 내 코드를 보면, 내가 생각한 방법은 빌딩을 건너가는 순간마다 항상 둘 중 하나를 선택해야만 한다는 전제가 있음을 알 수 있는데
이 전제 없이 문제를 풀 수 있는 방법인 것이다.

일단 사다리 갯수만큼 우선순위 큐에 차곡차곡 점프해야하는 높이들을 넣어준다.
그렇게 사다리 갯수보다 많아졌을 때, 그 때 가장 낮은 높이를 큐에서 빼고 그만큼 벽돌을 쓰면 된다.
벽돌이 동날 때까지 그렇게 하면 가장 최적의 선택을, 계산 몇번 하지 않고 할 수 있는 것이다 :D

import java.util.PriorityQueue;
 
class Solution {
    public int furthestBuilding(int[] heights, int bricks, int ladders) {
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();
 
        for (int i = 0; i < heights.length - 1; i++) {
            int diff = heights[i + 1] - heights[i];
            if (diff > 0) {
                priorityQueue.add(diff);
            }
            if (priorityQueue.size() > ladders) {
                int minDiff = priorityQueue.poll();
                bricks -= minDiff;
                if (bricks < 0) {
                    return i;
                }
            }
        }
 
        return heights.length - 1;
    }
}

시간복잡도 계산하기:
빌딩의 갯수를 N이라고 하면 for문을 n번 반복한다.
그리고 그 때마다 queue add 연산을 하고, 필요한경우 poll 연산도 한다.
for문 안은 2 * O(log N) 이므로 전체는 O(N logN) 일 것 같다.

gpt한테 답 확인하기

240217-151126