stack棧練習

為了你,我變成狼人模樣;

為了你,染上了瘋狂~

目錄

  • stack棧練習
      • 括號的分數
    • 單調棧
      • 模板框架
      • 小結
      • 下一個更大元素 I(單調棧+哈希)
      • 接雨水

stack棧練習

一種先進后出的線性數據結構

具體用法可參考往期文章或者維基介紹i

對應簡易練習

20. 有效的括號 - 力扣(LeetCode)

32. 最長有效括號 - 力扣(LeetCode)

括號的分數

856. 括號的分數 - 力扣(LeetCode)

本題主要是為了計算平衡括號字符串的分數,利用棧模擬并計算分數。遍歷字符串,在遇到右括號時根據最近匹配情況更新分數。

法一:利用棧,遍歷字符處理

左括號 (:壓入新的 0 作為當前層的分數占位符

右括號 )

  • 彈出棧頂值 v(最近未匹配括號計算的分數)
  • 分類更新分數:
    • v=0:最近是未匹配的左括號,形成 () 得1分
    • v>0:最近是已匹配括號組,形成 (A)2v
  • 將計算出的分數累加到新的棧頂(上一層)

利用棧可以記錄每層括號的中間分數,又因為他是先進后出的結構所以可以自動處理嵌套的關系,棧頂始終保存當前層的結果;遍歷完后最終棧頂即為整個字符串的總分;

class Solution {
public:int scoreOfParentheses(string s) {stack<int> st;st.push(0);for (auto c : s) {if (c == '(') {st.push(0);} else {int v=st.top();st.pop();if(v==0)st.top()+=1;elsest.top()+=v<<1;}}return st.top();}
};

法二:利用棧的思想,分層級處理(有點類似于后綴表達式)

仔細觀察,不難發現,題目中給出的字符串可匹配一定是合理的;所以每經歷到一次(就相當于進入了一個新的層級(觸發了嵌套關系)而遇到)就相當于退出了一個層級(結束嵌套);而遇到一個完整的()就是一個單位1,判斷這個單位1處在那個層級累加到結果中(因為每個單獨的()是相加的關系)即為所求;

這個方法通過維護一個動態乘數 n 來計算分數,核心思想是將嵌套括號轉化為深度相關的乘數累計

初始

  • n=1 作為基礎乘數(對應嵌套深度0)(n 表示當前括號所在深度的分數倍率)
  • an=0 作為總分累加器

遍歷字符串

  • 左括號 (
    • 將乘數 n 左移一位(n <<= 1),相當于乘數加倍(進入下一層)
  • 右括號 )
    • 將乘數 n 右移一位(n >>= 1),相當于恢復上層乘數(退出當前層)
    • 判斷:如果當前)與前一個字符形成()
      • 將當前乘數 n 累加到總分 an
class Solution {
public:int scoreOfParentheses(string s) {int n=1,an=0;for(int i=0;i<s.size();i++){if(s[i]=='(')n<<=1;elsen>>=1;if(s[i]==')'&&s[i-1]=='(')an+=n;}return an;}
};

和法一相比時間復雜度差不多(O(n)),都需要遍歷一次字符串;但是空間復雜度從原先的O(n)(棧空間)降低到了O(1)(常數空間);


單調棧

單調棧,你不乘哦

何為單調棧?顧名思義,單調棧即滿足單調性的棧結構。與單調隊列相比,其只在一端進行進出。

將一個元素插入單調棧時,為了維護棧的單調性,需要在保證將該元素插入到棧頂后整個棧滿足單調性的前提下彈出最少的元素。

原理:維護一個棧,保持棧內元素單調遞減。當處理新元素時,彈出所有比它小的元素,這些被彈出的元素與新元素形成一定的關系。

使用場景:適用于需要找到每個元素左邊或右邊第一個比它大或小的元素的問題。

實現步驟:
初始化空棧
對于每個元素:
彈出棧中所有比當前元素小的元素(這些元素能被當前元素看到)
計算當前元素能被棧中剩余元素看到的數量(即棧的大小)
將當前元素壓入棧

while(棧頂元素比入棧元素小或大 && 棧不空)
{棧頂元素彈出
}
元素入棧

模板框架

P5788 【模板】單調棧 - 洛谷

最基礎的模板題,需要我們尋找序列中每個元素"下一個更大元素"的位置(下標)

維護單調性使用棧維護"尚未找到下一個更大元素"的下標,保持棧底到棧頂對應的元素值單調遞減,當新元素a[i]比棧頂對應元素大時,說明新元素是棧頂元素的"下一個更大元素"

從左到右遍歷一遍序列

  • a[i] > 棧頂對應元素 → 彈出棧頂并記錄答案
  • 當前下標i入棧(等待后續元素為其尋找更大值)

遍歷結束后棧中剩余的元素(無更大元素),答案默認為0

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define pii pair<int,int>
#define fi first
#define se second
const int N=1e7;
int a[N],an[N];
stack<int> s;
void slove(){int n;cin>>n;for(int i=1;i<=n;i++)cin>>a[i];for(int i=1;i<=n;i++){if(s.size()==0){s.push(i);continue;}if(a[i]>a[s.top()]){while(s.size()&&a[i]>a[s.top()]){an[s.top()]=i;s.pop();}}s.push(i);}for(int i=1;i<=n;i++)cout<<an[i]<<' ';
} 
signed main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int _=1;//cin>>_;while(_--)slove();return 0;
}

同類型的套用模板的題目還有

739. 每日溫度 - 力扣(LeetCode)

[P2866 [USACO06NOV] Bad Hair Day S - 洛谷](https://www.luogu.com.cn/problem/P2866)

時間復雜度:O ( n ),每個元素最多入棧和出棧一次。
空間復雜度:O ( n ),最壞情況下所有元素都在棧中。


小結

單調棧是解決"第一個比當前元素大/小"這類問題的有效工具。本題通過維護一個單調遞增棧,保證了每個元素都能在O(1)均攤時間內找到左邊第一個比它小的數。關鍵在于理解為什么可以安全地彈出那些不會影響后續結果的元素,從而保持棧的單調性。

這種算法思想在很多場景下都有應用,比如計算直方圖的最大矩形面積、求解滑動窗口最大值等問題。掌握單調棧的使用可以大大提高解決這類問題的效率。


下一個更大元素 I(單調棧+哈希)

496. 下一個更大元素 I - 力扣(LeetCode)

本題需要為 nums1 中的每個元素在 nums2 中尋找下一個更大的元素(Next Greater Element)。核心思路是利用單調棧高效解決,并結合哈希表存儲結果。

1.遍歷 nums2 時維護一個遞減棧(棧底到棧頂元素遞減):

當前元素 i 若小于等于棧頂,直接入棧。

當前元素 i 若大于棧頂,則 i 是棧頂元素的下一個更大元素。此時將棧頂彈出并記錄映射 mp[棧頂] = i,直到棧頂不小于 i 或棧空。

結果:棧中最后剩余的元素在 nums2 中無下一個更大元素。

2.哈希表記錄映射

使用 unordered_map<int, int> mp 存儲 nums2 中元素的下一個更大元素。

當元素被彈出棧時,其下一個更大元素被記錄(即觸發彈出操作的元素)。

3.最后處理 nums1 的結果,找到每個對應的i即可

class Solution {
public:vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {vector<int> a;unordered_map<int,int> mp;stack <int> s;for(auto i:nums2){if(s.size()==0){s.push(i);continue;}while(s.size()&&i>s.top()){mp[s.top()]=i;s.pop();}s.push(i);}for(auto i:nums1){if(mp[i]==0)a.push_back(-1);elsea.push_back(mp[i]);}return a;}
};

接雨水

42. 接雨水 - 力扣(LeetCode)

本題要求計算柱狀圖中能接的雨水量。每個位置的存水量受短邊的影響;可以直接套用單調棧求解,這里寫出另外的兩種解法;

法一:動態規劃法

核心思路是通過構建左右方向的最大值數組,從而得到每個位置的理論盛水高度,最后減去實際柱高總和即得雨水總量。

  • 復制原始數組 b = a
  • 計算原始數組總和 ss(柱體總面積)

然后從兩個方向遍歷數組,維護兩個單調的數組

讓后計算理論盛水總量

  • 每個位置能盛水的理論高度:min(a[i], b[i])
  • 累加所有位置的理論高度:s += min(a[i], b[i])

計算實際雨水總量

  • 雨水總量 = 理論盛水總量 - 柱體總面積
  • return s - ss

最終呈現的時間復雜度為O(3n)

class Solution {
public:int trap(vector<int>& a) {vector<int> b=a;int ss=0;for(auto i:a)ss+=i;for(int i=1;i<a.size();i++)if(a[i]<a[i-1])a[i]=a[i-1];for(int i=b.size()-2;i>=0;i--)if(b[i]<b[i+1])b[i]=b[i+1];int s=0;for(int i=0;i<a.size();i++){s+=min(a[i],b[i]);}return s-ss;}
};

法二:雙指針逐層計算

核心策略是逐層水平累加雨水面積。通過從高度1開始逐步增加水平面,利用雙指針實時掃描有效容器邊界,計算每一層可容納的雨水寬度,最后減去柱體本身面積得到最終雨水總量。

  • 雙指針:l=0(左邊界),r=size-1(右邊界)
  • 當前高度:h=1(從最低水位開始)
  • 盛水輪廓面積:s=0(包括水和柱子的總面積)

逐層累加(當l<=r時循環)

  • 找左邊界:跳過所有高度小于當前層高h的柱子

    while (l < r && a[l] < h) l++;
    

    檢查終止條件:當左右指針相遇(l==r)且該處高度小于h時,退出循環

  • 找右邊界:跳過所有高度小于當前層高h的柱子

    while (l <= r && a[r] < h) r--;
    
  • 計算當前層寬:累加左右邊界間的寬度s += (r - l + 1)

最終雨水總量 = 盛水輪廓面積s - 柱子總面積ss

但是這個方法的時間復雜度為O(n·H),在最大高度H較小時使用比較好;空間相比上個有所減少;

class Solution {
public:int trap(vector<int>& a) {if (a.empty())return 0;int l = 0, r = a.size() - 1;int h = 1;int s = 0;while (l<=r) {while (l < r && a[l] < h) {l++;}if (l == r) {if (a[l] < h)break;}while (l <= r && a[r] < h) {r--;}if (l > r)break;s += (r - l + 1);h++;}int ss = 0;for (auto i : a) {ss += i;}return s - ss;}
};

類似練習

84. 柱狀圖中最大的矩形 - 力扣(LeetCode)求內部的面積(計算直方圖的最大矩形面積)


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/90245.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/90245.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/90245.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

詳細頁智能解析算法:洞悉海量頁面數據的核心技術

詳細頁智能解析算法&#xff1a;突破網頁數據提取瓶頸的核心技術剖析引言&#xff1a;數字時代的數據采集革命在當今數據驅動的商業環境中&#xff0c;詳細頁數據已成為企業決策的黃金資源。無論是電商商品詳情、金融公告還是新聞資訊&#xff0c;??有效提取結構化信息??直…

ubuntu環境如何安裝matlab2016

一、下載安裝文件&#xff08;里面包含激活包CRACK&#xff09;可從度盤下載&#xff1a;鏈接:https://pan.baidu.com/s/1wxmVMzXiSY4RIT0dyKkjZg?pwd26h6 復制這段內容打開「百度網盤APP 即可獲取」注&#xff1a;這里面包含三個文件&#xff0c;其中ISO包含安裝文件&#x…

Mybits-plus 表關聯查詢,嵌套查詢,子查詢示例演示

在 MyBatis-Plus 中實現表關聯查詢、嵌套查詢和子查詢&#xff0c;通常需要結合 XML 映射文件或 Select 注解編寫自定義 SQL。以下是具體示例演示&#xff1a;示例場景 假設有兩張表&#xff1a; 用戶表 userCREATE TABLE user (id BIGINT PRIMARY KEY,name VARCHAR(50),age IN…

Stable Diffusion Web 環境搭建

默認你的系統Ubuntu、CUDA、Conda等都存在&#xff0c;即具備運行深度學習模型的基礎環境 本人&#xff1a;Ubuntu22.04、CUDA11.8環境搭建 克隆項目并且創建環境 https://github.com/AUTOMATIC1111/stable-diffusion-webui conda create -n sd python3.10運行過程自動安裝依賴…

嵌入式系統中實現串口重定向

在嵌入式系統中實現串口重定向&#xff08;將標準輸出如 printf 函數輸出重定向到串口&#xff09;通常有以下幾種常用方法&#xff0c;下面結合具體代碼示例和適用場景進行說明&#xff1a; 1. 重寫 fputc 函數&#xff08;最常見、最基礎的方法&#xff09; 通過重寫標準庫中…

static補充知識點-代碼

public class Student {private static int age;//靜態的變量private double score;//非靜態的方法public void run(){}public static void go(){}public static void main(String[] args) {new Student().run();Student.go();} } public class Person {//2 &#xff1a; 賦初始…

使用泛型<T>,模塊化,反射思想進行多表數據推送

需求&#xff1a;有13個表&#xff0c;其中一個主表和12細表&#xff0c;主表用來記錄推送狀態&#xff0c;細表記錄12種病例的詳細信息&#xff0c;現在需要把這12張病例表數據進行數據推送&#xff1b;普通方法需要寫12個方法分別去推送數據然后修改狀態&#xff1b;現在可以…

光流 | RAFT光流算法如何改進提升

RAFT(Recurrent All-Pairs Field Transforms)作為ECCV 2020最佳論文,已成為光流估計領域的標桿模型。其通過構建4D相關體金字塔和GRU迭代優化機制,在精度與泛化性上實現了突破。但針對其計算效率、大位移處理、跨場景泛化等問題,研究者提出了多維度改進方案,核心方向可系…

linux/ubuntu日志管理--/dev/log 的本質與作用

文章目錄 **一、基本概念****二、技術細節:UNIX域套接字****三、在不同日志系統中的角色****四、應用程序如何使用 `dev/log`****五、查看和驗證 `/dev/log`****六、總結 `/dev/log` 的核心作用**一、基本概念 /dev/log 是一個 UNIX域套接字(Unix Domain Socket),是Linux系…

EMC整改案例之(1):汽車NFC進入模塊BCI整改

EMC整改案例(1):汽車NFC進入模塊BCI整改 在汽車電子系統中,NFC(Near Field Communication)進入模塊用于實現無鑰匙進入功能,但它在電磁兼容(EMC)測試中常面臨挑戰。本案例聚焦于BCI(Bulk Current Injection)測試整改,該測試模擬大電流注入對設備的影響。以下是基于…

2025年INS SCI2區,靈活交叉變異灰狼算法GWO_C/M+集群任務調度,深度解析+性能實測

目錄1.摘要2.灰狼算法GWO原理3.靈活交叉變異灰狼算法GWO_C/M4.結果展示5.參考文獻6.代碼獲取7.算法輔導應用定制讀者交流1.摘要 隨著云計算的快速發展&#xff0c;受自然現象啟發的任務調度算法逐漸成為研究的熱點。灰狼算法&#xff08;GWO&#xff09;因其強大的收斂性和易于…

Java常用加密算法詳解與實戰代碼 - 附可直接運行的測試示例

&#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有堅忍不拔之志 &#x1f390; 個人CSND主頁——Micro麥可樂的博客 &#x1f425;《Docker實操教程》專欄以最新的Centos版本為基礎進行Docker實操教程&#xff0c;入門到實戰 &#x1f33a;《RabbitMQ》…

2025開發者工具鏈革命:AI賦能的效率躍遷

目錄引言&#xff1a;效率焦慮下的開發者生存現狀一、智能代碼編輯器&#xff1a;從輔助到主導的進化1.1 GitHub Copilot&#xff1a;全能型AI助手1.2 Cursor Pro&#xff1a;極致編碼體驗1.3 飛算JavaAI&#xff1a;垂直領域顛覆者二、版本控制革命&#xff1a;Git的AI進化論2…

“虛空”的物理、哲學悖論

一、虛空并非“完全真空”&#xff1a;量子場論揭示的“真空不空” 物理真空的本質 現代物理學中的“真空”并非絕對的空無一物&#xff0c;而是量子場的基態&#xff08;能量最低狀態&#xff09;。根據量子場論&#xff1a; 虛粒子漲落&#xff1a;真空中持續發生量子漲落&am…

CSP-S模擬賽二總結(實際難度大于CSP-S)

T1 很簡短&#xff0c;也很好做&#xff0c;第一題直接場切。 我的方法 首先要明確一件事&#xff1a;就是如果選了 ax,ya_{x,y}ax,y?&#xff0c;那么就必然要選 ay,xa_{y,x}ay,x?&#xff0c;所以第一步就在 ax,ya_{x,y}ax,y? 的基礎上加上 ay,xa_{y,x}ay,x?。 然后我…

旋轉屏幕優化

1.問題背景 從google原生算法&#xff0c;可以知道其有2個比較大的缺陷&#xff1a; 1) 通過重力傳感器傳來的x&#xff0c;y&#xff0c;z軸的加速度合成之后只有一個垂直往下的加速度&#xff0c;如果此時用戶在別的方向上有加速度&#xff0c;那么通過反余弦、反正切等計算…

Java---day2

七、IDEA開發工具 &#x1f4e6; 一、下載 IntelliJ IDEA 官網地址&#xff1a; &#x1f517; IntelliJ IDEA – the IDE for Pro Java and Kotlin Development 版本選擇&#xff1a; 版本說明Community Edition (CE)免費開源版本&#xff0c;適合 Java、Kotlin、Android…

RAL-2025 | 清華大學數字孿生驅動的機器人視覺導航!VR-Robo:面向視覺機器人導航與運動的現實-模擬-現實框架

作者&#xff1a; Shaoting Zhu, Linzhan Mou, Derun Li, Baijun Ye, Runhan Huang, Hang Zhao單位&#xff1a;清華大學交叉信息研究院&#xff0c;上海期智研究院&#xff0c;Galaxea AI&#xff0c;上海交通大學電子信息與電氣工程學院論文標題&#xff1a;VR-Robo: A Real-…

碰一碰發視頻 + 矩陣系統聚合平臺源碼搭建,支持OEM

隨著短視頻生態與多平臺運營需求的融合&#xff0c;“碰一碰發視頻 矩陣系統” 聚合平臺成為內容創作者與企業營銷的新基建。這類系統需實現近場交互觸發、多平臺內容分發、數據聚合分析的全流程閉環&#xff0c;其源碼搭建與定制開發需突破硬件交互與軟件矩陣的技術壁壘。核心…

緩存雪崩、緩存穿透、緩存預熱、緩存更新、緩存降級

1. 緩存雪崩&#xff08;Cache Avalanche&#xff09;定義&#xff1a;緩存雪崩是指大量緩存中的數據在同一時間過期&#xff0c;導致大量請求同時訪問數據庫&#xff0c;造成數據庫壓力驟增&#xff0c;甚至可能導致數據庫崩潰。原因&#xff1a;多個緩存的 key 在同一時間過期…