leetcode
leetcode 2451 ~ 2500
找到 Alice 和 Bob 可以相遇的建筑

找到 Alice 和 Bob 可以相遇的建筑

难度:

标签:

题目描述

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 * 104
  • 1 <= heights[i] <= 109
  • 1 <= queries.length <= 5 * 104
  • queries[i] = [ai, bi]
  • 0 <= ai, bi <= heights.length - 1

代码结果

运行时间: 219 ms, 内存: 38.1 MB


/*
 * Problem: Given an array 'heights' representing the heights of buildings and an array 'queries' where each query contains two integers [a, b], 
 * we need to determine the leftmost building index where Alice starting at a and Bob starting at b can meet. 
 * Alice and Bob can only move to a building with a greater height than their current one. If no such building exists, return -1 for that query.
 */

import java.util.stream.IntStream;

public class Solution {
    public int[] canMeet(int[] heights, int[][] queries) {
        return IntStream.range(0, queries.length)
                .map(i -> findMeetingBuilding(heights, queries[i][0], queries[i][1]))
                .toArray();
    }

    private int findMeetingBuilding(int[] heights, int a, int b) {
        int n = heights.length;
        boolean[] reachableFromA = new boolean[n];
        boolean[] reachableFromB = new boolean[n];

        IntStream.range(a, n).takeWhile(i -> i == a || heights[i] > heights[a]).forEach(i -> reachableFromA[i] = true);
        IntStream.range(b, n).takeWhile(i -> i == b || heights[i] > heights[b]).forEach(i -> reachableFromB[i] = true);

        return IntStream.range(0, n).filter(i -> reachableFromA[i] && reachableFromB[i]).findFirst().orElse(-1);
    }
}

解释

方法:

这个题解使用了一个堆和一个数组来存储建筑信息。对于每个查询,首先检查 Alice 和 Bob 是否已经在同一个建筑中或者 Alice 可以直接移动到 Bob 的建筑,如果是,直接将答案设置为 Bob 的位置。否则,将 Alice 的位置和查询索引以元组形式添加到 Bob 所在建筑的列表中。然后,遍历所有建筑,对于每个建筑,将其左侧所有建筑的元组添加到堆中,并弹出堆中所有高度小于当前建筑高度的元组,将对应的答案设置为当前建筑的索引。这样,当处理完所有建筑后,就可以得到所有查询的答案。

时间复杂度:

O(q + n log n)

空间复杂度:

O(n)

代码细节讲解

🦆
为什么在处理查询时需要首先判断Alice和Bob是否在同一个建筑中或者Alice可以直接移动到Bob的建筑?这种判断的依据是什么?
此判断是为了处理最简单和直接的情况,以提高效率。如果Alice和Bob已经在同一个建筑中,那么Alice无需移动即可与Bob相遇。如果Alice可以直接移动到Bob的建筑,这意味着Alice位于Bob的左边且Alice的建筑不高于Bob的建筑,因此Alice可以直接移动到Bob的位置。这样直接判断可以减少不必要的计算,直接给出结果。
🦆
堆(priority queue)的使用在此题解中具体起到了什么作用?为什么选择使用堆而不是其他数据结构如队列或栈?
在此题解中,堆用于维护一个动态的,能够随时插入和删除元素的有序集合。堆确保了每次可以快速地获取并移除当前最小元素(这里是最低的建筑高度),这对于处理每个建筑时,检查并更新那些高度小于当前建筑高度的查询非常有用。使用堆而不是队列或栈的原因是,堆能够更高效地支持这种“动态的最值查询”操作,而普通的队列和栈不支持快速随机访问和中间元素的快速删除,这对于本问题中的需求来说是不够的。
🦆
题解中提到的`对于每个建筑,将其左侧所有建筑的元组添加到堆中`的操作,是否会导致堆中存在重复的建筑信息?这会影响性能吗?
操作中描述的`将其左侧所有建筑的元组添加到堆中`实际上指的是将当前建筑左侧相关的查询添加到堆中,而不是建筑本身。每个查询只因关联的Bob的位置一次性添加到堆中。因此,不会有重复的建筑信息加入到堆中。这种方式确保了堆中每个元素都是独立的查询,不会因重复的建筑信息而影响性能。
🦆
当使用堆从中移除所有高度小于当前建筑高度的元组时,这个操作如何确保已经处理过的查询不会被错误地更新?
在题解中,每次处理一个新的建筑时,堆中会移除所有高度小于该建筑高度的元组,并将对应的查询答案设置为当前建筑的索引。这个操作确保一旦一个查询被处理(即被设置了答案),它就不会再次出现在堆中。堆中只存储还未找到有效答案的查询。这样通过逐步移除满足条件的最小元素,可以确保每个查询只被处理一次,避免了错误更新。

相关问题