2940. Find Building Where Alice and Bob Can Meet
Difficulty: Hard
Topics: Array, Binary Search, Stack, Binary Indexed Tree, Segment Tree, Heap (Priority Queue), Monotonic Stack
You are given a 0-indexed array heights of positive integers, where heights[i] represents the height of the ith building.
If a person is in building i, they can move to any other building j if and only if i < j and heights[i] < heights[j].
You are also given another array queries where queries[i] = [ai, bi]. On the ith query, Alice is in building ai while Bob is in building bi.
Return an array ans where ans[i] is the index of the leftmost building where Alice and Bob can meet on the ith query. If Alice and Bob cannot move to a common building on query i, set ans[i] to -1.
Example 1:
- Input: heights = [6,4,8,5,2,7], queries = [[0,1],[0,3],[2,4],[3,4],[2,2]]
 - Output: [2,5,-1,5,2]
 - 
Explanation: In the first query, Alice and Bob can move to building 2 since heights[0] < heights[2] and heights[1] < heights[2].
- In the second query, Alice and Bob can move to building 5 since heights[0] < heights[5] and heights[3] < heights[5].
 - In the third query, Alice cannot meet Bob since Alice cannot move to any other building.
 - In the fourth query, Alice and Bob can move to building 5 since heights[3] < heights[5] and heights[4] < heights[5].
 - In the fifth query, Alice and Bob are already in the same building.
 - For ans[i] != -1, It can be shown that ans[i] is the leftmost building where Alice and Bob can meet.
 - For ans[i] == -1, It can be shown that there is no building where Alice and Bob can meet.
 
 
Example 2:
- Input: heights = [5,3,8,2,6,1,4,6], queries = [[0,7],[3,5],[5,2],[3,0],[1,6]]
 - Output: [7,6,-1,4,6]
 - 
Explanation: In the first query, Alice can directly move to Bob's building since heights[0] < heights[7].
- In the second query, Alice and Bob can move to building 6 since heights[3] < heights[6] and heights[5] < heights[6].
 - In the third query, Alice cannot meet Bob since Bob cannot move to any other building.
 - In the fourth query, Alice and Bob can move to building 4 since heights[3] < heights[4] and heights[0] < heights[4].
 - In the fifth query, Alice can directly move to Bob's building since heights[1] < heights[6].
 - For ans[i] != -1, It can be shown that ans[i] is the leftmost building where Alice and Bob can meet.
 - For ans[i] == -1, It can be shown that there is no building where Alice and Bob can meet.
 
 
Constraints:
1 <= heights.length <= 5 * 1041 <= heights[i] <= 1091 <= queries.length <= 5 * 104queries[i] = [ai, bi]0 <= ai, bi <= heights.length - 1
Hint:
- For each query 
[x, y], ifx > y, swapxandy. Now, we can assume thatx <= y. - For each query 
[x, y], ifx == yorheights[x] < heights[y], then the answer isysincex ≤ y. - Otherwise, we need to find the smallest index 
tsuch thaty < tandheights[x] < heights[t]. Note thatheights[y] <= heights[x], soheights[x] < heights[t]is a sufficient condition. - To find index 
tfor each query, sort the queries in descending order ofy. Iterate over the queries while maintaining a monotonic stack which we can binary search over to find indext. 
Solution:
The problem requires determining the leftmost building where Alice and Bob can meet given their starting buildings and movement rules. Each query involves finding a meeting point based on building heights. This is challenging due to the constraints on movement and the need for efficient computation.
Key Points
- Alice and Bob can move to another building if its height is strictly greater than the current building.
 - For each query, find the leftmost valid meeting point, or return 
-1if no such building exists. - The constraints demand a solution better than a naive O(n²) approach.
 
Approach
- 
Observations:
- If 
a == b, Alice and Bob are already at the same building. - If 
heights[a] < heights[b], Bob's building is the meeting point. - Otherwise, find the smallest building index 
t > bwhere:heights[a] < heights[t]- 
heights[b] <= heights[t](asbis already less thanain height comparison). 
 
 - If 
 - 
Optimization Using Monotonic Stack:
- A monotonic stack helps efficiently track the valid buildings Alice and Bob can move to. Buildings are added to the stack in a way that ensures heights are in decreasing order, enabling fast binary searches.
 
 - 
Query Sorting:
- Sort the queries in descending order of 
bto process buildings with larger indices first. This ensures that we build the stack efficiently as we move from higher to lower indices. 
 - Sort the queries in descending order of 
 - 
Binary Search on Stack:
- For each query, use binary search on the monotonic stack to find the smallest index 
tthat satisfies the conditions. 
 - For each query, use binary search on the monotonic stack to find the smallest index 
 
Plan
- Sort queries based on the larger of the two indices (
b) in descending order. - Traverse the array backward while maintaining a monotonic stack of valid indices.
 - For each query, check trivial cases (
a == borheights[a] < heights[b]). - For non-trivial cases, use the stack to find the leftmost valid building via binary search.
 - Return the results in the original query order.
 
Solution Steps
- 
Preprocess Queries:
- Ensure 
a <= bin each query for consistency. - Sort queries by 
bin descending order. 
 - Ensure 
 - 
Iterate Through Queries:
- Maintain a monotonic stack as we traverse the array.
 - For each query:
- If 
a == b, the answer isb. - If 
heights[a] < heights[b], the answer isb. - Otherwise, use the stack to find the smallest valid index 
t > b. 
 - If 
 
 - 
Binary Search on Stack:
- Use binary search to quickly find the smallest index 
ton the stack that satisfiesheights[t] > heights[a]. 
 - Use binary search to quickly find the smallest index 
 - 
Restore Original Order:
- Map results back to the original query indices.
 
 Return Results.
Let's implement this solution in PHP: 2940. Find Building Where Alice and Bob Can Meet
<?php
/**
 * @param Integer[] $heights
 * @param Integer[][] $queries
 * @return Integer[]
 */
function leftmostBuildingQueries($heights, $queries) {
    ...
    ...
    ...
    /**
     * go to ./solution.php
     */
}
/**
 * @param $queries
 * @return array
 */
private function getIndexedQueries($queries) {
    ...
    ...
    ...
    /**
     * go to ./solution.php
     */
}
/**
 * @param $stack
 * @param $a
 * @param $heights
 * @return mixed|null
 */
private function findUpperBound($stack, $a, $heights) {
    ...
    ...
    ...
    /**
     * go to ./solution.php
     */
}
class IndexedQuery {
    public $queryIndex;
    public $a; // Alice's index
    public $b; // Bob's index
    /**
     * @param $queryIndex
     * @param $a
     * @param $b
     */
    public function __construct($queryIndex, $a, $b) {
        $this->queryIndex = $queryIndex;
        $this->a = $a;
        $this->b = $b;
    }
}
// Test the function
$heights = [6, 4, 8, 5, 2, 7];
$queries = [[0, 1], [0, 3], [2, 4], [3, 4], [2, 2]];
print_r(leftmostBuildingQueries($heights, $queries));
$heights = [5, 3, 8, 2, 6, 1, 4, 6];
$queries = [[0, 7], [3, 5], [5, 2], [3, 0], [1, 6]];
print_r(leftmostBuildingQueries($heights, $queries));
?>
Explanation:
- 
Sorting Queries: The queries are sorted by 
bin descending order to process larger indices first, which allows us to update our monotonic stack as we process. - Monotonic Stack: The stack is used to keep track of building indices where Alice and Bob can meet. We only keep buildings that have a height larger than any previously seen buildings in the stack.
 - 
Binary Search: When answering each query, we use binary search to efficiently find the smallest index 
twhere the conditions are met. 
Example Walkthrough
Input:
heights = [6,4,8,5,2,7]queries = [[0,1],[0,3],[2,4],[3,4],[2,2]]
Process:
- 
Sort Queries:
- Indexed queries: 
[(2,4), (3,4), (0,3), (0,1), (2,2)] 
 - Indexed queries: 
 - 
Build Monotonic Stack:
- Start at the highest index and add indices to the stack:
- At index 5: Stack = 
[5] - At index 4: Stack = 
[5, 4] - ...
 
 - At index 5: Stack = 
 
 - Start at the highest index and add indices to the stack:
 - 
Query Processing:
- For query 
[0,1],heights[0] < heights[1]: Result = 2. - ...
 
 - For query 
 
Output:
[2, 5, -1, 5, 2]
Time Complexity
- 
Query Sorting: 
O(Q log Q)where Q is the number of queries. - 
Monotonic Stack Construction: 
O(N)where N is the length ofheights. - 
Binary Search for Each Query: 
O(Q log N). 
Overall: O(N + Q log (Q + N)).
Output for Example
Input:
$heights = [6, 4, 8, 5, 2, 7];
$queries = [[0, 1], [0, 3], [2, 4], [3, 4], [2, 2]];
Output:
print_r(findBuilding($heights, $queries)); // [2, 5, -1, 5, 2]
This approach efficiently handles large constraints by leveraging a monotonic stack and binary search. It ensures optimal query processing while maintaining correctness.
Contact Links
If you found this series helpful, please consider giving the repository a star on GitHub or sharing the post on your favorite social networks 😍. Your support would mean a lot to me!
![]()
If you want more helpful content like this, feel free to follow me:
              
    
Top comments (0)