本题来自左神《程序员面试代码指南》“单调栈结构”题目。

题目

给定一个不含有重复值的数组 arr,找到每一个 i 位置左边和右边离 i 位置最近且值比 arr[i] 小的位置。返回所有位置相应的信息。

举例

输入:

arr = {3, 4, 1, 5, 6, 2, 7}

返回如下二维数组作为结果:

{{-1,  2}, // -1表示不存在,整体含义为:arr[0]左边离arr[0]最近且比arr[0]小的是arr[-1],//                    arr[0]右边离arr[0]最近且比arr[0]小的是arr[2],{ 0,  2},{-1, -1},{ 2,  5},{ 3,  5},{ 2, -1},{ 5, -1},
}

题解

本题实现时间复杂度为 O(n^2) 的解是非常容易的,每个位置分别向左和向右遍历一下即可,本文不再详述。

若要想时间复杂度达到 O(n),需要用到单调栈结构。

下面我们详细讲解单调栈结构。

1、原问题:无重复元素的单调栈

思路总结:每一次从 栈顶大于 当前元素的弹出



(过程草稿)

代码:

// O(n),无重复元素的单调栈
public static int[][] getNearLessNoRepeat(int[] arr) {int[][] res = new int[arr.length][2];Stack<Integer> stack = new Stack<>(); // 单调栈for (int i = 0; i < arr.length; i++) {while (!stack.isEmpty() && arr[i] < stack.peek()) { // 若当前位置元素[小于]栈顶位置元素,则一直弹出栈顶元素,直到不小于为止int popIndex = stack.pop();int leftLessIndex = stack.isEmpty() ? -1 : stack.peek(); // 栈中当前元素上方的元素res[popIndex][0] = leftLessIndex; // 记录弹出元素[左边],[第一个小于弹出元素的元素]的下标res[popIndex][1] = i;             // 记录弹出元素[右边],[第一个小于弹出元素的元素]的下标}stack.push(i); // 当前元素入栈}// 遍历完成,对栈中剩余元素进行清算while (!stack.isEmpty()) {int popIndex = stack.pop();int leftIndex = stack.isEmpty() ? -1 : stack.peek();res[popIndex][0] = leftIndex;res[popIndex][1] = -1;}return res;
}

2、进阶问题:含有重复元素的单调栈

其实整个过程和原问题的解法差不多。只不过是将重复的元素压在一起,并看作一个整体进行弹出。


(过程草稿)

代码:

import java.util.*;//单调栈结构
public class Main {public static int[][] getNearLess(int[] arr) {int[][] res = new int[arr.length][2];ArrayDeque<List<Integer>> stack = new ArrayDeque<>();for (int i = 0; i < arr.length; i++) {while (!stack.isEmpty() && arr[i] < arr[stack.peek().get(0)]) {List<Integer> topList = stack.pop();int leftLessIdx = stack.isEmpty() ? -1 : stack.peek().get(stack.peek().size() - 1);for (Integer n : topList) {res[n][0] = leftLessIdx;res[n][1] = i;}}if (!stack.isEmpty() && arr[i] == arr[stack.peek().get(0)]) {stack.peek().add(i);} else {List<Integer> list = new ArrayList<>();list.add(i);stack.push(list);}}while (!stack.isEmpty()) {List<Integer> topList = stack.pop();int leftLessIdx = stack.isEmpty() ? -1 : stack.peek().get(stack.peek().size() - 1);for (Integer n : topList) {res[n][0] = leftLessIdx;res[n][1] = -1;}}return res;}public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt(); // 元素总个数int[] arr = new int[n];for (int i = 0; i < n; i++) {arr[i] = sc.nextInt();}int[][] res = getNearLess(arr);for (int i = 0; i < n; i++) {System.out.println(res[i][0] + " " + res[i][1]);}}
}

输入:

9 3 1 3 4 3 5 3 2 2

输出:

-1 1
-1 -1
1 7
2 4
1 7
4 6
1 7
1 -1
1 -1

参考

  • 单调栈结构 - CSDN博客
  • 单调栈结构 TIAN_HE - CSDN博客

左神算法:单调栈结构(Java版)相关推荐

  1. 常考数据结构与算法:单调栈结构

    在数组中想找到一个数, 左边和右边比这个数小. 且离这个数最近的位置. import java.util.ArrayList; import java.util.List; import java.u ...

  2. 左神算法:求最大子矩阵的大小(Java版)

    本题来自左神<程序员面试代码指南>"求最大子矩阵的大小"题目. 题目 给定一个整型矩阵 map,其中的值只有0和1两种,求其中全是1的所有矩形区域中,最大的矩形区域为1 ...

  3. 左神算法:最大值减去最小值小于或等于num的子数组的数量(Java版)

    本题来自左神<程序员面试代码指南>"最大值减去最小值小于或等于num的子数组的数量"题目. 题目 给定数组 arr 和整数 num,共返回有多少个子数组满足如下情况: ...

  4. java 堆排序算法_堆排序算法的讲解及Java版实现

    这篇文章主要介绍了堆排序算法的讲解及Java版实现,堆排序基于堆这种数据结构,在本文中对堆的概念也有补充介绍,需要的朋友可以参考下 堆是数据结构中的一种重要结构,了解了"堆"的概念 ...

  5. 算法--猫扑素数--java版

    算法–猫扑素数–java版 简介 猫扑素数: 形如以 2 开头, 之后跟任意多个 3 的十进制整数如果是个素数, 则它是猫扑素数. 如 2, 23, 233, 2333, 23333 都是猫扑素数, ...

  6. 左神算法:用栈来求解限制后的汉诺塔问题(Java版)

    本题来自左神<程序员面试代码指南>"用栈来求解汉诺塔问题"题目. 题目 限制后的汉诺塔问题如下: 限制不能从最左侧的塔直接移动到最右侧,也不能从最右侧直接移动到最左侧, ...

  7. 左神算法:用一个栈实现另一个栈的排序(Java版)

    本题源自左神<程序员面试代码指南>"用一个栈实现另一个栈的排序"题目. 题目 在一个栈中元素的类型为整型,现在想将该栈从栈顶到栈底按从大到小的顺序排序,只许申请一个栈, ...

  8. 左神算法:可见的山峰对数量(有重复值的情况)(Java版)

    本题来自左神<程序员面试代码指南>"可见的山峰对数量"题目. 题目 牛客在线OJ:可见的山峰对数量(进阶) 一个不含有负数的数组可以代表一圈环形山,每个位置的值代表山的 ...

  9. 左神算法:将搜索二叉树转换成双向链表(Java版)

    本题来自左神<程序员代码面试指南>"将搜索二叉树转换成双向链表"题目. 题目 对二叉树的节点来说,有本身的值域,有指向左孩子节点和右孩子节点的两个指针:对双向链表的节点 ...

最新文章

  1. 划分微型计算机的标志是,划分微型计算机的标志为
  2. HTML学习笔记(三)样式CSS
  3. 查询mysql存储数据大小_MySQL如何查询数据占用存储空间的大小?
  4. STM32 基础系列教程 24 - USB_HID_key
  5. 论面向组合子程序设计方法 之 oracle
  6. Fabric--CA 应用与配置
  7. SpringBoot中英文切换/国际化——java后端怎么用预置文本的内容替换web网页内容(Resource Bundle)
  8. linux 性能教程,Linux系统下常见性能分析工具的使用
  9. LeetCode - Easy - 696. Count Binary Substrings
  10. 【项目管理】《挑战埃及》沙盘介绍
  11. 小小一方士 C# Async\Await 之 上传/下载文件进度条实现原理
  12. HTML常用排版标签
  13. cad缩放_CAD常见问题详解,解决你当前的烦恼
  14. js保留两位小数并四舍五入的方法
  15. win10虚拟机搭建群晖nas碰到的一些问题
  16. 明天终于要到公司开工了
  17. python反距离权重法_先从IDW(反距离权重)插值开始吧
  18. 5天突击GRE(155+170+4.0)
  19. vue:element ui分页改变pageSize,触发两次回调请求
  20. 宏基d260linux系统,Devuan GNU+Linux 2.0.0 稳定版发布,无systemd自由版本

热门文章

  1. POJ - 2018 Best Cow Fences(二分+最长连续子段和)
  2. POJ - 2449 Remmarguts' Date(第k短路:spfa+A*)
  3. salt远程执行python脚本_SaltStack远程执行Windows job程序(黑窗口)填坑经过
  4. uva1616二分加误差处理
  5. 排序算法-06堆排序(python实现)
  6. dqn在训练过程中loss越来越大_DQN算法实现注意事项及排错方法
  7. UVA10173(求凸包的面积最小外接矩形)
  8. VIM进阶-模式mode
  9. “白加黑”远控木马技术分析及手杀方案
  10. socket connec连接超时处理