Blage's Coding Blage's Coding
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
  • 数组

  • 链表

  • 字符串

  • 二叉树

  • 动态规划

  • 深搜回溯

  • 数学贪心

  • 堆栈队列

    • 394.字符串解码
    • 32. 最长有效括号
    • 739. 每日温度
    • 1130. 叶值的最小代价生成树
    • 84. 柱状图中最大的矩形
    • 42.接雨水
    • 85. 最大矩形
    • 239.滑动窗口最大值
    • 6891. 机器人碰撞
    • 445. 两数相加 II
    • 2762. 不间断子数组
    • 6919. 使数组中的所有元素都等于零
    • 862. 和至少为 K 的最短子数组
    • 1499. 满足不等式的最大值
    • 2856. 删除数对后的最小数组长度
    • 901. 股票价格跨度
    • 2034. 股票价格波动
    • 1488. 避免洪水泛滥
    • 2940. 找到 Alice 和 Bob 可以相遇的建筑
      • 1.单调栈+跳表查询
      • 2.离线+最小堆
        • 大小顺序如何保证?
    • 2454. 下一个更大元素 IV
  • 前缀和

  • 算法设计

  • 位运算

  • WA

  • 算法
  • 堆栈队列
phan
2023-11-20
目录

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

# 2940. 找到 Alice 和 Bob 可以相遇的建筑 (opens new window)

# 1.单调栈+跳表查询

思路:使用单调栈维护每个元素右侧第一个比它的元素的索引,并将结果保存到数组。查询时,需要遍历数组找到同时满足比heights[queries[0]]和heights[queries[1]]都大的索引位置,遍历过程类似于跳表。

极端条件下100001,1,2,3,4,5,6 . . . 100000,时间复杂度达到O(nq),结果用例似乎没卡。可以使用二分查找,进一步优化遍历rightMaximum数组,时间复杂度为O(log(n)q)。

查询时对于两人的位置min,max存在两种情况:

  • heights[min]小于heights[max]:那么min可以直接跳到max位置,查询结束。
  • heights[min]大于等于heights[max]:则需要根据max依次搜索“最大右侧索引数组”,对于每次max可跳跃的位置midInx,当且仅当heights[midInx]也满足大于heights[min],两个人才可同时移动到该位置。
class Solution {
    public int[] leftmostBuildingQueries(int[] heights, int[][] queries) {
        int[] rightMaximum = new int[heights.length];
        Stack<int[]> stack = new Stack<>();
        Arrays.fill(rightMaximum,-1);
        for (int i = 0; i < heights.length; i++) {
            while (!stack.isEmpty() && heights[i] > stack.peek()[0]) {
                int[] pop = stack.pop();
                rightMaximum[pop[1]] = i;
            }
            stack.push(new int[]{heights[i], i});
        }

        int[] res = new int[queries.length];
        for (int i = 0; i < queries.length; i++) {
            int min = Math.min(queries[i][0], queries[i][1]);
            int max = Math.max(queries[i][0], queries[i][1]);
            if(min==max||heights[min]<heights[max]) res[i] = max;
            else{
                 int midInx = rightMaximum[max];
                while (midInx!=-1) {
                    int mid = heights[midInx];
                    if (mid > heights[min]) {
                        res[i] = midInx;
                        break;
                    }
                    midInx = rightMaximum[midInx];
                }
                if(midInx==-1) res[i]=-1;
            }
        }
        return res;
    }
}
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

# 2.离线+最小堆

离线:按照自己定义的某种顺序,来进行回答询问。而不按照输入的查询顺序。

离线预处理:对于每个查询(a,b),假设a<b,保存每个以索引b为右端点的所有查询对。即Map<Integer,List<int[]>>,其中每个查询对保存左端点的高度heights[b],以及查询索引。

定义优先级队列(最小堆)按照左查询端点高度升序排序的最小堆。

遍历heights数组,对于第i个位置元素:

  • 将最小堆顶元素高度小于heights[i]的查询对依次出队,查询结果即为i。
  • 以第i个位置为查询右端点的所有查询对入对。

# 大小顺序如何保证?

  • 根据最小堆,可以保证出队时,一定有heights[i]大于左端点元素高度heights[a]
  • 预处理构造查询对时,保证左端点元素heights[a]一定大于等于右端点元素heights[b]
  • 因此位置 i 一定是两个人可以到达的位置。
编辑 (opens new window)
#Leetcode#堆栈队列
上次更新: 2023/12/15, 15:49:57
1488. 避免洪水泛滥
2454. 下一个更大元素 IV

← 1488. 避免洪水泛滥 2454. 下一个更大元素 IV→

Theme by Vdoing | Copyright © 2023-2024 blageCoder
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式