Java 之「单调栈」:从入门到实战

Java 单调栈:从入门到实战

文章目录

  • Java 单调栈:从入门到实战
    • 引言
    • 什么是单调栈?
      • 单调递增栈
      • 单调递减栈
    • 单调栈的应用场景
    • Java 实现单调栈
      • 代码示例:下一个更大元素
        • 代码解析
    • 单调栈的优势
    • 实战应用:股票价格跨度
      • 代码示例
        • 代码解析
    • 总结
      • 参考资料

引言

在 Java 编程中,数据结构的选择和使用往往是解决复杂问题的关键。单调栈(Monotonic Stack)作为一种高效的数据结构,能够在 O(n) 时间复杂度内解决许多与单调性相关的问题,例如“下一个更大元素”、“股票价格跨度”等。对于 CSDN 的读者来说,深入理解单调栈不仅能提升代码能力,还能在面试和项目中脱颖而出。本文将带你从单调栈的基本概念入手,逐步深入到 Java 实现与实战应用,附上详细代码示例,让你轻松掌握这一利器!


什么是单调栈?

单调栈是一种特殊的栈结构,其核心在于保持栈内元素的单调性,即从栈底到栈顶元素要么单调递增,要么单调递减。在操作时,单调栈会通过弹出不符合单调性的元素来维持这一特性,从而在处理实时单调性问题时表现出色。

单调递增栈

  • 定义:栈内元素从栈底到栈顶单调递增。
  • 入栈规则:当新元素入栈时,如果栈顶元素大于或等于新元素,则不断弹出栈顶元素,直到栈顶小于新元素或栈为空。

单调递减栈

  • 定义:栈内元素从栈底到栈顶单调递减。
  • 入栈规则:当新元素入栈时,如果栈顶元素小于或等于新元素,则不断弹出栈顶元素,直到栈顶大于新元素或栈为空。

单调栈的这种动态调整机制,使其在特定场景下非常高效。


单调栈的应用场景

单调栈在算法和实际项目中有广泛应用,以下是几个经典场景:

  1. 下一个更大元素(Next Greater Element):在数组中为每个元素找到右边第一个比它大的元素。
  2. 股票价格跨度(Stock Span Problem):计算连续天数中股票价格不高于当天的最大天数。
  3. 直方图中最大矩形(Largest Rectangle in Histogram):在直方图中找到面积最大的矩形。
  4. 温度预测:在温度数组中找到每个温度下一次更高温度出现的日子。

这些问题有一个共同点:需要快速找到某种单调关系,而单调栈正是解决这类问题的“杀手锏”。


Java 实现单调栈

在 Java 中,我们可以利用 java.util.Stack 类来实现单调栈。下面以“下一个更大元素”问题为例,展示单调递减栈的实现。

代码示例:下一个更大元素

import java.util.Stack;public class MonotonicStackExample {public static int[] nextGreaterElement(int[] nums) {int n = nums.length;int[] result = new int[n];Stack<Integer> stack = new Stack<>(); // 单调递减栈// 从右向左遍历数组for (int i = n - 1; i >= 0; i--) {// 弹出所有小于当前元素的栈内元素while (!stack.isEmpty() && stack.peek() <= nums[i]) {stack.pop();}// 如果栈不为空,栈顶即为下一个更大元素,否则为 -1result[i] = stack.isEmpty() ? -1 : stack.peek();// 当前元素入栈stack.push(nums[i]);}return result;}public static void main(String[] args) {int[] nums = {2, 1, 2, 4, 3};int[] result = nextGreaterElement(nums);for (int num : result) {System.out.print(num + " "); // 输出: 4 2 4 -1 -1}}
}
代码解析
  • 栈的单调性:栈内元素保持单调递减。
  • 遍历方向:从右向左遍历,便于找到右侧的更大元素。
  • 逻辑
    1. 对于当前元素 nums[i],弹出栈内所有小于等于它的元素。
    2. 若栈为空,则右侧无更大元素,记为 -1;否则栈顶即为答案。
    3. 将当前元素压入栈,继续处理下一个元素。

单调栈的优势

  1. 时间复杂度:每个元素最多入栈和出栈一次,总时间复杂度为 O(n)。
  2. 空间复杂度:最坏情况下栈存储所有元素,空间复杂度为 O(n)。
  3. 实时性:单调栈适合动态数据流场景,能实时维护单调性。

实战应用:股票价格跨度

问题描述:给定一个股票价格数组,计算每一天股票价格不高于当天的连续天数(包括当天)。

解法:使用单调递增栈,栈内存储价格及其对应的跨度,动态累加跨度。

代码示例

import java.util.Stack;public class StockSpan {public static int[] stockSpan(int[] prices) {int n = prices.length;int[] spans = new int[n];Stack<int[]> stack = new Stack<>(); // 存储 [价格, 跨度]for (int i = 0; i < n; i++) {int span = 1;// 弹出栈内小于等于当前价格的元素,累加其跨度while (!stack.isEmpty() && stack.peek()[0] <= prices[i]) {span += stack.pop()[1];}spans[i] = span;stack.push(new int[]{prices[i], span});}return spans;}public static void main(String[] args) {int[] prices = {100, 80, 60, 70, 60, 75, 85};int[] spans = stockSpan(prices);for (int span : spans) {System.out.print(span + " "); // 输出: 1 1 1 2 1 4 6}}
}
代码解析
  • 栈的单调性:栈内价格单调递增。
  • 跨度计算:当遇到更高价格时,弹出栈内较小的价格并累加其跨度。
  • 结果spans[i] 表示第 i 天对应的跨度。

总结

单调栈凭借其高效性和简洁性,成为解决单调性问题的利器。本文从概念到代码,详细介绍了 Java 中单调栈的实现与应用,涵盖了“下一个更大元素”和“股票价格跨度”两个经典案例。无论你是准备算法面试,还是在项目中优化代码,单调栈都值得你深入掌握。

希望这篇博客能为你带来启发!如果有疑问或想了解更多应用场景,欢迎在评论区留言交流。

参考资料

  • LeetCode: Next Greater Element
  • GeeksforGeeks: Stock Span Problem

希望这篇博客能帮你在面试或项目中游刃有余!有疑问欢迎留言讨论,喜欢请点赞关注哦!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/73056.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Golang】defer与recover的组合使用

在Go语言中&#xff0c;defer和recover是两个关键特性&#xff0c;通常结合使用以处理资源管理和异常恢复。以下是它们的核心应用场景及使用示例&#xff1a; 1. defer 的应用场景 defer用于延迟执行函数调用&#xff0c;确保在函数退出前执行特定操作。主要用途包括&#xff…

CSS 中flex - grow、flex - shrink和flex - basis属性的含义及它们在弹性盒布局中的协同作用。

大白话CSS 中flex - grow、flex - shrink和flex - basis属性的含义及它们在弹性盒布局中的协同作用。 在 CSS 的弹性盒布局&#xff08;Flexbox&#xff09;里&#xff0c;flex-grow、flex-shrink 和 flex-basis 这三个属性对弹性元素的尺寸和伸缩性起着关键作用。下面为你详细…

OpenGL ES ->乒乓缓冲,计算只用两个帧缓冲对象(Frame Buffer Object)+叠加多个滤镜作用后的Bitmap

乒乓缓冲核心思想 不使用乒乓缓冲&#xff0c;如果要每个滤镜作用下的绘制内容&#xff0c;也就是这个滤镜作用下的帧缓冲&#xff0c;需要创建一个Frame Buffer Object加上对应的Frame Buffer Object Texture使用乒乓缓冲&#xff0c;只用两个Frame Buffer Object加上对应的F…

【HarmonyOS NEXT】关键资产存储开发案例

在 iOS 开发中 Keychain 是一个非常安全的存储系统&#xff0c;用于保存敏感信息&#xff0c;如密码、证书、密钥等。与文件系统不同&#xff0c;Keychain 提供了更高的安全性&#xff0c;因为它对数据进行了加密&#xff0c;并且只有经过授权的应用程序才能访问存储的数据。那…

ccfcsp1901线性分类器

//线性分类器 #include<iostream> using namespace std; int main(){int n,m;cin>>n>>m;int x[1000],y[1000];char z[1000];for(int i0;i<n;i){cin>>x[i]>>y[i];cin>>z[i];}int a[20],b[20],c[20];for(int i0;i<m;i){cin>>a[i…

Spring Boot 整合 OpenFeign 教程

精心整理了最新的面试资料和简历模板&#xff0c;有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 Spring Boot 整合 OpenFeign 教程 一、OpenFeign 简介 OpenFeign 是 Netflix 开源的声明式 HTTP 客户端&#xff0c;通过接口和注解简化服务间 HTTP 调用。…

APM 仿真遥控指南

地面站开发了一段时间了&#xff0c;由于没有硬件&#xff0c;所以一直在 APM 模拟器中验证。我们已经实现了 MAVLink 消息接收和解析&#xff0c;显示无人机状态&#xff0c;给无人机发送消息&#xff0c;实现一键起飞&#xff0c;飞往指定地点&#xff0c;降落&#xff0c;返…

C语言入门教程100讲(4)输入输出

文章目录 1. 什么是输入输出&#xff1f;2. 标准输入输出函数2.1 printf 函数2.2 scanf 函数 3. 格式化占位符4. 示例代码代码解析&#xff1a;输出结果&#xff1a; 5. 常见问题问题 1&#xff1a;scanf 中的 & 是什么作用&#xff1f;问题 2&#xff1a;printf 和 scanf …

《信息系统安全》(第一次上机实验报告)

实验一 &#xff1a;网络协议分析工具Wireshark 一 实验目的 学习使用网络协议分析工具Wireshark的方法&#xff0c;并用它来分析一些协议。 二实验原理 TCP/IP协议族中网络层、传输层、应用层相关重要协议原理。网络协议分析工具Wireshark的工作原理和基本使用规则。 三 实…

城市街拍人像自拍电影风格Lr调色教程,手机滤镜PS+Lightroom预设下载!

调色教程 城市街拍人像自拍的电影风格 Lr 调色&#xff0c;是利用 Adobe Lightroom 软件&#xff0c;对在城市街景中拍摄的人像自拍照片进行后期处理&#xff0c;使其呈现出电影画面般独特的视觉质感与艺术氛围。通过一系列调色操作&#xff0c;改变照片的色彩、明暗、对比等元…

自学Python创建强大AI:从入门到实现DeepSeek级别的AI

人工智能&#xff08;AI&#xff09;是当今科技领域最热门的方向之一&#xff0c;而Python是AI开发的首选语言。无论是机器学习、深度学习还是自然语言处理&#xff0c;Python都提供了丰富的库和工具。如果你梦想创建一个像DeepSeek这样强大的AI系统&#xff0c;本文将为你提供…

Qt/C++项目积累:4.远程升级工具 - 4.1 项目设想

背景&#xff1a; 桌面程序一般都支持远程升级&#xff0c;也是比较常用的场景设计。如酷狗音乐的升级&#xff0c;会提供两个选项&#xff0c;自动帮助安装或是新版本提醒&#xff0c;由用户来决定是否升级&#xff0c;都属于远程升级的应用及策略。 看看经过这块的功能了解及…

(一)丶Windows安装RabbitMQ可能会遇到的问题

一丶可能会忘了配置ERLang的环境变量 二丶执行命令时报错 第一步 rabbitmq-plugins enable rabbitmq_management 第二部 rabbitmqctl status 三丶修改.erlang.cookie 文件 1.找到C盘目下的.erlang.cookie文件 C:\Users\admin\.erlang.cookie C:\Windows\System32\config\sys…

Amdahl 定律

Amdahl 定律是用来表示&#xff0c;当提高系统某部分性能时对整个系统的影响&#xff0c;其公式如下&#xff1a; a表示我们提升部分初始耗时比例&#xff0c;k是我们的提升倍率&#xff0c;通过这个公式我们可以轻松的得知对每一部分的提醒&#xff0c;对整个系统带来的影响…

HW华为流程管理体系精髓提炼华为流程运营体系(124页PPT)(文末有下载方式)

资料解读&#xff1a;HW华为流程管理体系精髓提炼华为流程运营体系&#xff08;124页PPT&#xff09; 详细资料请看本解读文章的最后内容。 华为作为全球领先的科技公司&#xff0c;其流程管理体系的构建与运营是其成功的关键之一。本文将从华为流程管理体系的核心理念、构建…

Powershell WSL导出导入ubuntu22.04.5子系统

导出Linux子系统 导出位置在C盘下,根据自己的实际情况更改即可Write-Host "export ubuntu22.04.5" -ForegroundColor Green wsl --export Ubuntu-22.04 c:\Ubuntu-22.04.tar 导入Linux子系统 好处是目录可用在任意磁盘路径,便于迁移不同的设备之间Write-Host &quo…

【Attention】SKAttention

SKAttention选择核注意力 标题&#xff1a;SKAttention 期刊&#xff1a;IEEE2019 代码&#xff1a; https://github.com/implus/SKNet 简介&#xff1a; 动机:增大感受野来提升性能、多尺度信息聚合方式解决的问题&#xff1a;自适应调整感受野大小创新性:提出选择性内核…

解决Popwindow宽高的问题。

问题 在使用Popwindow进行自定义的过程中&#xff0c;需要设置popwindow的宽高。但是宽高很多时候容易出问题。比如下面的例子。 布局文件如下 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.andr…

MySQL数据库精研之旅第二期:库操作的深度探索

专栏&#xff1a;MySQL数据库成长记 个人主页&#xff1a;手握风云 目录 一、查看数据库 二、创建数据库 2.1. 语法 2.2. 示例 三、字符集编码和校验(排序)规则 3.1. 查看数据库支持的字符集编码 3.2. 查看数据库支持的排序规则 3.3. 不同的字串集与排序规则对数据库的…