2940. Find Building Where Alice and Bob Can Meet
2940. Find Building Where Alice and Bob Can Meet
[Problem]
Array
Binary Search
Stack
Binary Indexed Tree
Segment Tree
Heap (Priority Queue)
Monotonic Stack
Intuition
- The problem revolves around determining the leftmost building where Alice and Bob can meet, based on specific movement constraints (i.e., moving to a taller building).
- Since Alice and Bob may not always be able to move to a common building directly, a deferred query processing can be used.
- By leveraging height constraints and maintaining pending queries, we can efficiently compute the result.
Approach
- Deferred Queries
- Use an array of lists (
lists
) to store pending queries for each building where Alice or Bob cannot directly move to the target building. - Populate the
lists
during the initial traversal of queries.
- Use an array of lists (
- Immediate Meeting
- If Alice and Bob can immediately meet based on their starting buildings and the height conditions, record the result in the
res
array.
- If Alice and Bob can immediately meet based on their starting buildings and the height conditions, record the result in the
- Priority Queue
- Utilize a priority queue to handle deferred queries efficiently.
- Each query in the queue is processed when the height of the current building allows it.
- Finally iterate over each building, updating results for pending queries where the height condition is now satisfied.
Complexity Analysis
- Time Complexity: O(n + qlog q):
- Initial query processing:
O(q)
, whereq
is the no. of queries. - Processing deferred queries:
O(n+qlog q)
, wheren
is the no. of buildings &O(qlogq)
for priority queue operations.
- Initial query processing:
- Space Complexity: O(n + q):
- Storage for
lists
:O(n+q)
to store all pending queries. - Priority queue:
O(q)
- Storage for
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
class Solution {
public int[] leftmostBuildingQueries(int[] heights, int[][] queries) {
//Array of lists to store pending queries for each building
List<int[]>[] lists = new ArrayList[heights.length];
// Initialize the result array with -1 (meaning no meeting point found)
int[] res = new int[queries.length];
Arrays.fill(res, -1);
for (int i = 0; i < queries.length; i++) {
int aIndex = queries[i][0]; // Alice starting building index
int bIndex = queries[i][1]; // Bob starting building index
// Case 1: Alice starts to the right of Bob
if (aIndex > bIndex) {
// If Alice can directly move to Bob's building
if (heights[aIndex] > heights[bIndex]) {
res[i] = aIndex;
} else {
// Otherwise, store the query for processing later
if (lists[aIndex] == null)
lists[aIndex] = new ArrayList<>();
lists[aIndex].add(new int[] { heights[bIndex], i });
}
}
// Case 2: Bob starts to the right of Alice
else if (aIndex < bIndex) {
// If Bob can directly move to Alice's building
if (heights[aIndex] < heights[bIndex]) {
res[i] = bIndex;
} else {
// Otherwise, store the query for processing later
if (lists[bIndex] == null)
lists[bIndex] = new ArrayList<>();
lists[bIndex].add(new int[] { heights[aIndex], i });
}
}
// Case 3: Both start at the same building
else {
res[i] = aIndex;
}
}
// priority queue(minHeap) to handle pending queries sorted by heights
PriorityQueue<int[]> minHeap = new PriorityQueue<>((a, b) -> a[0] - b[0]);
// Iterate over each building to process pending queries
for (int i = 0; i < heights.length; i++) {
// Process queries in the priority queue where height is less than the current building's height
while (!minHeap.isEmpty() && minHeap.peek()[0] < heights[i]) {
res[minHeap.poll()[1]] = i;
}
// Add pending queries for the current building to the priority queue
if (lists[i] != null) {
for (int[] arr : lists[i]) {
minHeap.add(arr);
}
}
}
return res;
}
}
This post is licensed under CC BY 4.0 by the author.