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.pswp.cn/web/73056.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/73056.shtml
英文地址,請注明出處:http://en.pswp.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. 不同的字串集與排序規則對數據庫的…