2940. Find Building Where Alice and Bob Can Meet


문제 링크


내 코드

Solution 참고..


Solution

Approach 1: Monotonic Stack

  • 54ms, 262.74MB
  • Complexity
    • Let nn be the size of the array heights and qq be the number of queries in the queries array.
    • Time Complexity: O(qlogn+n)O(q \cdot \log n + n)
    • Space Complexity: O(n+q)O(n + q)
class Solution {
public:
    vector<int> leftmostBuildingQueries(vector<int>& heights,
                                        vector<vector<int>>& queries) {
        vector<pair<int, int>> monoStack;
        vector<int> result(queries.size(), -1);
        vector<vector<pair<int, int>>> newQueries(heights.size());
        for (int i = 0; i < queries.size(); i++) {
            int a = queries[i][0];
            int b = queries[i][1];
            if (a > b) swap(a, b);
            if (heights[b] > heights[a] || a == b)
                result[i] = b;
            else
                newQueries[b].push_back({heights[a], i});
        }

        for (int i = heights.size() - 1; i >= 0; i--) {
            int monoStackSize = monoStack.size();
            for (auto& [a, b] : newQueries[i]) {
                int position = search(a, monoStack);
                if (position < monoStackSize && position >= 0)
                    result[b] = monoStack[position].second;
            }
            while (!monoStack.empty() && monoStack.back().first <= heights[i])
                monoStack.pop_back();
            monoStack.push_back({heights[i], i});
        }
        return result;
    }

private:
    int search(int height, vector<pair<int, int>>& monoStack) {
        int left = 0;
        int right = monoStack.size() - 1;
        int ans = -1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (monoStack[mid].first > height) {
                ans = max(ans, mid);
                left = mid + 1;
            } else
                right = mid - 1;
        }
        return ans;
    }
};

GPT

아래 코드는 빌딩들의 높이를 나타내는 배열 heights에 대해, 쿼리로 주어진 [a,b][a, b] 구간에서 다음 조건을 만족하는 왼쪽에서 가장 오른쪽에 위치한 빌딩(인덱스)을 찾는 문제로 보입니다.

  • 쿼리는 [a,b][a, b] 형태이지만, 내부적으로 aba \le b로 정렬하며, 빌딩 aa의 높이보다 더 높은 빌딩이 구간 a..ba..b 내에서 어디 있는지(혹은 찾지 못하면 기본적으로 bb를 반환) 등을 판별하는 로직을 수행하고 있습니다.

정확한 문제 설명이 주어지지는 않았지만, 코드 흐름 및 사용된 자료구조(모노톤 스택, 이진 탐색 등)를 통해 “왼쪽에서 시작하여 빌딩 aa와 비교했을 때 더 높은 빌딩이 b~? 사이 어디에 있는지 찾기” 혹은 “어느 지점에서 빌딩 aa보다 높은 빌딩을 처음 만나게 되는가?” 같은 문제로 추측할 수 있습니다.

아래에서는 코드의 흐름을 단계별로 살펴보겠습니다.


1. 쿼리 분류 & 초기 결과 설정

for (int i = 0; i < queries.size(); i++) {
    int a = queries[i][0];
    int b = queries[i][1];
    if (a > b) swap(a, b);

    // heights[b] > heights[a] 또는 a == b이면, 
    // 곧바로 결과 = b 로 설정
    if (heights[b] > heights[a] || a == b)
        result[i] = b;
    else
        // (b)번 인덱스를 key로 하는 리스트에 (heights[a], i) 푸시
        newQueries[b].push_back({heights[a], i});
}
  • 각 쿼리 [a, b]가 주어졌을 때, a > b라면 스왑해서 항상 a <= b가 되도록 맞춥니다.
  • 만약 heights[b]heights[a]보다 크거나, a == b라면,
    • 이미 답이 자명하기 때문에 result[i] = b로 처리하고 끝냅니다.
  • 그렇지 않은 경우(즉, heights[b] <= heights[a]이고 a != b),
    • 나중에 b 위치에서 무언가 처리할 일이 생기므로, newQueries[b](heights[a], i)를 저장해 둡니다.
    • 여기서 i는 쿼리의 인덱스, heights[a]는 비교 기준이 될 높이.

즉, 즉시 결정될 수 있는 쿼리는 미리 답을 적어두고, 그렇지 않은 쿼리는 “나중에 b 위치를 역순으로 탐색하며” 해결한다는 방식을 쓰고 있습니다.


2. 모노톤 스택을 이용한 역방향 처리

for (int i = heights.size() - 1; i >= 0; i--) {
    int monoStackSize = monoStack.size();

    // newQueries[i] = {(heights[a], indexOfQuery), ...} 
    // i 위치에서 처리해야 할 쿼리들
    for (auto& [a, queryIndex] : newQueries[i]) {
        // 모노톤 스택 내부에서 'a보다 큰' 빌딩을 이진 탐색
        int position = search(a, monoStack);
        if (position < monoStackSize && position >= 0)
            // 모노톤 스택에서 찾은 빌딩의 인덱스(monoStack[position].second)로 쿼리 결과 설정
            result[queryIndex] = monoStack[position].second;
    }

    // 모노톤 스택을 유지: heights[i] 이하인 것들은 pop
    while (!monoStack.empty() && monoStack.back().first <= heights[i])
        monoStack.pop_back();

    // 그 뒤 (heights[i], i)를 push
    monoStack.push_back({heights[i], i});
}

(A) newQueries[i] 처리

  • 인덱스 ii오른쪽에서 왼쪽(i=n-1 down to 0)으로 훑으면서, newQueries[i]에 쌓아 두었던 “i 위치에서 처리해야 할 쿼리들”을 처리합니다.
    • newQueries[i]에는 (heights[a], queryIndex) 형태의 데이터가 들어있는데, 이는 “빌딩 a의 높이와 비교했을 때 더 큰 빌딩을 모노톤 스택에서 찾는다”는 뜻으로 해석할 수 있습니다.

(B) search(a, monoStack)

  • 이 함수는 모노톤 스택(내림차순 정렬)에서 “a보다 큰 높이(first > a)를 만족하는 원소 중 가능한 한 오른쪽(스택의 뒤쪽)?”을 찾는 이진 탐색 로직으로 보입니다.
    • 실제 코드를 보면 if (monoStack[mid].first > height) {...} else {...} 형태입니다.
    • ans를 갱신하면서, monoStack[mid].first > height이면 ans = max(ans, mid); left = mid+1; 처리를 합니다.
      • 이는 보다 오른쪽(인덱스가 큰) 위치를 찾아가는 방식.
    • 최종 ans를 반환하면, 그 위치가 가장 오른쪽에서 height를 초과하는 원소가 있는 인덱스가 됩니다. (또는 -1)

(C) 모노톤 스택 업데이트

  • 내림차순”을 유지하려고 하는 것으로 보입니다.
    • 현재 인덱스 i의 빌딩 높이 heights[i]보다 작거나 같은 원소는 스택에서 pop.
    • 그런 다음 (heights[i], i)를 push.
    • 이렇게 하면 스택은 “오른쪽 → 왼쪽”으로 갈수록 늘어만 가는(non-decreasing) 높이 순서를 유지하게 됩니다.
    • 검색할 때 search(a, monoStack)a보다 (strictly greater) 요소의 위치를 찾으니, 사실상 “오른쪽에서 왼쪽으로 볼 때, 오름차순인 높이들” 을 스택에 저장하는 셈입니다.

결과적으로,

  • 오른쪽 끝에서부터 왼쪽으로 진행하면서, 현재 위치 i에서 “자신보다 낮거나 같은” 빌딩을 스택에서 없애버림 → 스택에는 “나보다 더 높은 빌딩”만 남음.
  • search(a, monoStack)를 통해 a보다 더 높은 빌딩 중 가장 나중에(오른쪽에) 들어있는 빌딩의 인덱스를 찾을 수 있음.
  • 그 인덱스를 가져와 쿼리 결과에 대입.

3. search 함수 (이진 탐색)

int search(int height, vector<pair<int, int>>& monoStack) {
    int left = 0;
    int right = monoStack.size() - 1;
    int ans = -1;
    while (left <= right) {
        int mid = (left + right) / 2;
        if (monoStack[mid].first > height) {
            ans = max(ans, mid);
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return ans;
}
  • monoStack[mid].first > height이면, ans = max(ans, mid) 하고 더 오른쪽도 가능할지 확인하기 위해 left = mid+1;
  • 그렇지 않으면 right = mid - 1;
  • 결국 이진 탐색 종료 후 ans가 “가장 오른쪽에서 height보다 큰 원소”의 인덱스 를 반환합니다.
  • 찾지 못하면 -1이 남게 됩니다.

스택이 내림차순 정렬이라고 할 때,

  • 인덱스가 커질수록 높이가 낮아지는 구조를 상상할 수 있으나, 여기서는 스택의 0번이 오른쪽 끝, 마지막 push가 왼쪽 끝에 해당**할 수 있습니다.
  • 코드 로직상 “오른쪽에서 왼쪽”으로 빌딩을 훑고 있으니, push도 “스택의 뒤에” 집어넣고, pop은 “스택의 뒤에서” 일어납니다.
  • 따라서 monoStack[0]이 가장 오른쪽 빌딩, monoStack.back()이 현재 i번째 빌딩이 됩니다.
  • 이진 탐색으로 a보다 큰 빌딩 중 가장 인덱스가 큰(스택에서 맨 앞쪽) 원소를 찾는 방식으로 보입니다. (조금 헷갈리긴 하지만, 코드가 그런 구조를 취하고 있음)

요약 정리

  1. 쿼리 전처리

    • ([a, b])에서 a > b면 스왑 → 항상 (a \le b).
    • 만약 heights[b] > heights[a]거나 a == b면, 결과가 바로 b로 정해짐.
    • 그렇지 않으면, “나중에 (b) 위치에서 heights[a]보다 더 높은 빌딩의 인덱스를 찾아야 한다” → newQueries[b].push_back({heights[a], 쿼리인덱스}).
  2. 역순 루프(i = n-1..0) + 모노톤 스택

    • newQueries[i]를 처리하면서, 각 (heights[a], queryIndex)에 대해 스택에서 a보다 더 높은 빌딩 중 가장 나중(오른쪽)의 인덱스를 이진 탐색.
    • 스택은 “heights[i]보다 작거나 같은 빌딩”을 pop하여, 내림차순 성질을 유지.
    • (heights[i], i)를 push.
  3. 이진 탐색 search(a, monoStack)

    • monoStack에서 a보다 큰 first를 가진 원소 중 스택 인덱스가 가장 큰(오른쪽)” 을 찾는다.
    • 찾으면 해당 빌딩의 인덱스(second)를 결과로 반환.

결론적으로…

  • 왼쪽 빌딩(a)오른쪽 빌딩(b) 가 주어질 때, “오른쪽으로 진행하면서 ‘a’보다 더 높은 빌딩을 찾으면 그 인덱스가 답이 된다. 만약 못 찾으면 b가 답” 같은 상황을 역순으로 모노톤 스택을 구축하며 해결하는 기법입니다.
  • 모노톤 스택에 쿼리를 나중에 한 번에 처리(newQueries[b] 목록 사용)함으로써, “어떤 시점(i)에서 처리해야 할 쿼리가 있으면, 현재 스택 상태를 통해 빠르게 답을 찾는다”는 구조를 취하고 있습니다.
  • 시간 복잡도는 대체로 O(nlogn)O(n log n) 수준(스택 유지 O(n), 쿼리 이진 탐색이 O(qlogn)O(q \log n) 등)일 것으로 보이며, 쿼리의 수와 빌딩의 수에 비례해 동작합니다.

즉, 이 코드는 “오른쪽에서 왼쪽으로 빌딩 높이를 모노톤(내림차순)으로 스택에 저장”하면서, “각종 [a,b][a, b] 쿼리에서, aa의 높이보다 더 높은 빌딩을 bb의 위치 근처에서(혹은 그보다 오른쪽에서) 찾고자 하는” 문제를 효율적으로 해결하는 방법이라고 이해할 수 있습니다.


Approach 2: Priority Queue

  • 257ms, 321.31MB
  • Complexity
    • Let nn be the size of the array heights and qq be the number of queries in the queries array.
    • Time Complexity: O(qlogq+n)O(q \log q + n)
    • Space Complexity: O(n+q)O(n + q)
class Solution {
public:
    vector<int> leftmostBuildingQueries(vector<int>& heights,
                                        vector<vector<int>>& queries) {
        vector<vector<vector<int>>> storeQueries(heights.size());
        priority_queue<vector<int>, vector<vector<int>>, greater<vector<int>>>
            maxIndex;
        vector<int> result(queries.size(), -1);

        // Store the mappings for all queries in storeQueries.
        for (int currQuery = 0; currQuery < queries.size(); currQuery++) {
            int a = queries[currQuery][0], b = queries[currQuery][1];
            if (a < b && heights[a] < heights[b]) {
                result[currQuery] = b;
            } else if (a > b && heights[a] > heights[b]) {
                result[currQuery] = a;
            } else if (a == b) {
                result[currQuery] = a;
            } else {
                storeQueries[max(a, b)].push_back(
                    {max(heights[a], heights[b]), currQuery});
            }
        }

        for (int index = 0; index < heights.size(); index++) {
            // If the priority queue's minimum pair value is less than the
            // current index of height, it is an answer to the query.
            while (!maxIndex.empty() && maxIndex.top()[0] < heights[index]) {
                result[maxIndex.top()[1]] = index;
                maxIndex.pop();
            }
            // Push the with their maximum index as the current index in the
            // priority queue.
            for (auto& element : storeQueries[index]) {
                maxIndex.push(element);
            }
        }
        return result;
    }
};

GPT

아래 코드는 “두 빌딩 (a,b)(a, b) 가 주어졌을 때, 어떤 조건에 따라 ‘왼쪽에서 오른쪽으로 스캔했을 때 처음으로 만나는, max(heights[a],heights[b])\max(\text{heights}[a], \text{heights}[b])보다 높은 빌딩의 인덱스’ 를 구하는 문제”로 추측할 수 있습니다.
다만 문제 원문이 주어지지 않았으므로, 코드를 통해 역으로 로직을 유추해보겠습니다.


전체 코드 흐름

vector<int> leftmostBuildingQueries(vector<int>& heights,
                                    vector<vector<int>>& queries) {
    // (1) 쿼리별로 "즉시 결정 가능한" 경우는 바로 result에 기록,
    //     그렇지 않은 쿼리는 따로 storeQueries[max(a, b)]에 저장.
    vector<vector<vector<int>>> storeQueries(heights.size());
    priority_queue<vector<int>, vector<vector<int>>, greater<vector<int>>> maxIndex;
    vector<int> result(queries.size(), -1);

    for (int currQuery = 0; currQuery < queries.size(); currQuery++) {
        int a = queries[currQuery][0], b = queries[currQuery][1];

        // a < b 이고 heights[a] < heights[b] 이면 즉시 result = b
        // a > b 이고 heights[a] > heights[b] 이면 즉시 result = a
        // a == b이면 당연히 result = a
        // 그 외 경우 => storeQueries[max(a,b)] 에 {max(heights[a], heights[b]), 쿼리번호} 저장
        if (a < b && heights[a] < heights[b]) {
            result[currQuery] = b;
        } else if (a > b && heights[a] > heights[b]) {
            result[currQuery] = a;
        } else if (a == b) {
            result[currQuery] = a;
        } else {
            storeQueries[max(a, b)].push_back({max(heights[a], heights[b]), currQuery});
        }
    }

    // (2) 왼쪽부터 빌딩을 스캔하며, 
    //     "이전에 스택(우선순위큐)에서 더 높은 빌딩을 기다리고 있던 쿼리들"을 해소
    for (int index = 0; index < (int)heights.size(); index++) {
        // (2a) 현재 빌딩의 높이(heights[index])가
        //      우선순위큐 top에 있는 "목표 높이"보다 더 크다면, 그 쿼리는 index로 답변 가능
        while (!maxIndex.empty() && maxIndex.top()[0] < heights[index]) {
            int queryIndex = maxIndex.top()[1];
            result[queryIndex] = index;
            maxIndex.pop();
        }

        // (2b) 지금 index에서 "추가로 발생하는" 쿼리(= storeQueries[index])를 큐에 삽입
        //      이 쿼리들은 "max(heights[a], heights[b])보다 큰 빌딩을 찾아야 함"
        for (auto& element : storeQueries[index]) {
            // element = {targetHeight, queryIndex}
            maxIndex.push(element);
        }
    }

    return result;
}

이 로직을 토대로, 단계별 작동 방식을 살펴보겠습니다.


1. 쿼리 전처리 (즉시 답변 가능한 경우)

for (int currQuery = 0; currQuery < queries.size(); currQuery++) {
    int a = queries[currQuery][0], b = queries[currQuery][1];

    if (a < b && heights[a] < heights[b]) {
        result[currQuery] = b;
    } else if (a > b && heights[a] > heights[b]) {
        result[currQuery] = a;
    } else if (a == b) {
        result[currQuery] = a;
    } else {
        storeQueries[max(a, b)].push_back({max(heights[a], heights[b]), currQuery});
    }
}
  • 쿼리는 ((a, b)) 형태입니다.
  • 다음과 같은 3가지 케이스면 즉시 답이 정해집니다.
    1. a<ba < b 그리고 heights[a]<heights[b]\text{heights}[a] < \text{heights}[b]
      • 결과 = bb
    2. a>ba > b 그리고 heights[a]>heights[b]\text{heights}[a] > \text{heights}[b]
      • 결과 = aa
    3. a==ba == b
      • 결과 = (a) (즉 “자기 자신”)
  • 그 외의 경우(즉, “상대방 빌딩이 즉시 답이 되지 않는 상황”)에는,
    • max(a,b)\max(a, b) 인덱스 위치의 storeQueries[max(a,b)]에 {max(heights[a],heights[b])\max(\text{heights}[a], \text{heights}[b]), 쿼리번호} 형태로 저장해 둡니다.
    • 이것은 “나중에 왼쪽에서 오른쪽으로 스캔하다가, max(heights[a],heights[b])\max(\text{heights}[a], \text{heights}[b]) 보다 높은 빌딩이 나타나면 그 때가 답”이라는 의미로 볼 수 있습니다.

간단히 말해, 건너편 빌딩이 더 높으면 바로 답이고, 그렇지 않으면 더 높은 빌딩을 찾으러 간다는 로직처럼 보입니다.


2. 왼쪽에서 오른쪽 스캔 & 우선순위 큐

for (int index = 0; index < heights.size(); index++) {
    // (A) 현재 빌딩의 높이로 해결 가능한(기다리고 있던) 쿼리들 처리
    while (!maxIndex.empty() && maxIndex.top()[0] < heights[index]) {
        int queryIndex = maxIndex.top()[1];
        result[queryIndex] = index;
        maxIndex.pop();
    }

    // (B) 이제 index에 도달했으니,
    //     storeQueries[index]에 쿼리가 있으면 큐에 등록
    for (auto& element : storeQueries[index]) {
        // element = {targetHeight, queryIndex}
        maxIndex.push(element);
    }
}
  • maxIndex: priority_queue<vector<int>, vector<vector<int>>, greater<vector<int>>>
    • 즉, ‘가장 작은 vector가 top()’ 이 되는 Min-Heap입니다.
    • vector의 형태는 {targetHeight, queryIndex}.
    • greater<vector<int>> 비교 시, 첫 번째 원소(targetHeight)를 우선 비교하고, 같으면 두 번째 원소(queryIndex)를 비교합니다.

(A) 현재 빌딩으로 해결할 수 있는 쿼리

  • while (!maxIndex.empty() && maxIndex.top()[0] < heights[index]) { ... }
    • 즉, 큐의 top(최소 targetHeight)이 heights[index]보다 작으면,
      • targetHeighttargetHeight보다 더 큰 빌딩”을 찾는 쿼리는 현재 index로 해결 가능하다는 뜻 → result[queryIndex] = index;
      • 해당 쿼리를 큐에서 pop.
    • 이 과정을 top이 더 이상 heights[index]보다 작지 않을 때까지 반복합니다.

(B) storeQueries[index]에 쌓인 쿼리 등록

  • 전처리 단계에서 “max(a,b)\max(a, b) 위치에서 (targetHeight, queryIndex)를 큐에 넣는다”라고 했는데, 그 “max(a,b)\max(a,b) 위치”가 바로 index가 될 때, 이제야 큐에 들어갑니다.
  • 즉, index에 도달하기 전에는 해결할 수도, 큐에 들어가지도 않은 상태였다가, index가 되어서야 “이제부터 index 이후 빌딩 중 targetHeighttargetHeight보다 높은 빌딩이 있으면 답”이라는 식으로 큐에 들어간다는 로직입니다.

정리: “왼쪽에서 첫 번째로 더 높은 빌딩” 찾기?

코드를 통해 유추하면 대략 이런 식의 문제를 푸는 것으로 보입니다:

  • 쿼리 (a,b)(a, b)가 주어졌을 때,
    1. 만약 빌딩 (b)가 빌딩 (a)보다 (인덱스상 오른쪽이면서) 더 높다면, 답은 (b).
      • 즉시 result = b.
    2. 만약 빌딩 (a)가 빌딩 (b)보다 (인덱스상 왼쪽이면서) 더 높다면, 답은 (a).
      • 즉시 result = a.
    3. 만약 a==ba == b 면 자기 자신이 답.
    4. 그 외 경우(즉, max(a,b)\max(a,b) 쪽 빌딩이 당장 더 높지 않다면) → “max(heights[a],heights[b])\max(\text{heights}[a], \text{heights}[b])”보다 큰 빌딩을 왼쪽부터 차례대로 찾는다. 제일 처음 발견한 인덱스가 답. (못 찾으면 -1)

이 로직을 지원하기 위해,

  • (1) 즉시 판별 가능하면 result에 바로 기록.
  • (2) 나머지는 storeQueries[ max(a,b) ]{max(heights[a],heights[b]),queryIndex}\{ \max(\text{heights}[a], \text{heights}[b]), \text{queryIndex}\} 형태로 저장.
  • (3) index=0부터 index=n-1까지 순회:
    • 이미 큐에 들어와 있던 쿼리들 중 “targetHeight < heights[index]”는 index로 해결(= 첫 번째로 만난 더 높은 빌딩).
    • 그런 뒤 storeQueries[index]에 새로 등록된(“index에서 시작하는” 느낌의) 쿼리들을 큐에 push → 다음 인덱스들에서 해결될 수 있도록.

이로써 모든 쿼리에 대해, 왼쪽에서 오른쪽으로 스캔하면서 처음 발견되는 “heights[index] > targetHeight” 빌딩의 위치를 구할 수 있게 됩니다.


핵심 포인트 요약

  1. 즉시 답변 가능한 쿼리 처리

    • (a,b)(a, b) 중 “오른쪽 빌딩이 더 높은 경우” \rightarrow result = b
    • “왼쪽 빌딩이 더 높은 경우” \rightarrow result = a
    • “둘이 같은 인덱스일 경우” \rightarrow result = a
    • (이후 설명에서 “인덱스가 오른쪽”이라는 것은 a<b일 때를 가정)
  2. 그렇지 않은 쿼리는

    • max(heights[a],heights[b])\max(\text{heights}[a], \text{heights}[b])보다 더 높은 빌딩을 찾아야 함”
    • 이 요청을 storeQueries[max(a,b)]에 저장.
  3. 왼→오 스캔

    • 각 인덱스 i에 도달하면, 지금까지 큐에 쌓여있던 쿼리들 중, “목표 높이 < heights[i]” 인 것들을 result = i로 해결 & 큐에서 제거.
    • storeQueries[i]에 쌓여 있던 쿼리(지금부터 i 이후를 탐색해야 하는 것들)를 큐에 등록.
  4. 우선순위 큐(Min-Heap)는 “targetHeight가 작은 순”대로 정렬되므로, “현재 빌딩이 그보다 크면 즉시 해결”하는 식의 그리디 처리 가능.

  5. 최종적으로

    • 스캔이 끝날 때까지 “더 높은 빌딩”을 찾지 못한 쿼리는 -1로 남습니다.
    • 찾았다면 해당 인덱스로 결과가 갱신됩니다.

결론적으로

이 코드는

  • (1) 특정한 빠른 판별 조건으로 일부 쿼리를 즉시 해결하고,
  • (2) 나머지는 “max(heights[a],heights[b])\max(\text{heights}[a], \text{heights}[b])보다 큰 빌딩을 왼쪽에서부터 찾겠다” 라는 아이디어로 처리,
  • (3) 왼→오 순회하면서 현재 빌딩이 기다리던 목표 높이들보다 큰지 확인 후, 맞으면 “처음으로 만난 더 높은 빌딩” 인덱스를 결과로 설정

하는 그리디 + 우선순위 큐 방식이라 볼 수 있습니다.

“Leftmost Building Queries”라는 이름처럼, “어떤 목표 높이보다 ‘더 높은 빌딩’을 왼쪽부터 최초로 발견하는 위치”를 빠르게 찾아주는 로직으로 추정됩니다.

  • 즉시 답이 정해지는 경우(건너편 빌딩이 더 높거나 같을 때) → 바로 답
  • 그 외 경우 → 전체를 왼쪽부터 스캔하며 처음으로 목표 높이보다 큰 빌딩을 만나면 그 인덱스를 답으로.
  • 만약 끝까지 없으면 -1.