主頁 > 軟體設計 > 一道Medium,兩道Hard帶你刷爆力扣單調堆疊(模板解題,學不會來捶我,建議收藏)

一道Medium,兩道Hard帶你刷爆力扣單調堆疊(模板解題,學不會來捶我,建議收藏)

2021-09-01 14:56:00 軟體設計

Preface

繼上篇【面試高頻】詳解單調堆疊,今天我們來講述一下如何用我給出的單調堆疊模板刷題,

所謂單調堆疊其實就是堆疊內元素具有單調性, 常用于解決下一個更大元素 這種問題,

我們會講一下其中最具代表性的三道題,其中一道Medium,兩道Hard,保證你看完一定有所識訓:

  • 739. 每日溫度 - 力扣

  • 42. 接雨水 - 力扣

  • 84. 柱狀圖中最大的矩形 - 力扣

 // 單調堆疊模板,如果不懂可以看我的上篇文章
 for (遍歷這個陣列) {
     while (堆疊不為空 && 堆疊頂元素與當前陣列元素比較) {
         出堆疊;
     }
     入堆疊; 
 }

739. 每日溫度

Description

image-20210828114330017

Simulation

思路:我們先列一個表格分析一下示例資料是怎么來的

第1天第2天第3天第4天第5天第6天第7天第8天
溫度7374757169727673
下一個更高的溫度第2天第3天第7天第6天第6天第7天
天數差11421100

首先想到的當然是暴力解法,兩層 for 回圈挨個遍歷一遍,計算天數差即可,時間復雜度O(n^2),

get到暴力解法也很重要,畢竟不是什么時候都能想到最優解,而且我們還可以基于暴力解法進行下一步優化,

題目中要求計算下一個更高的溫度的天數差,其實就是要找到自己右邊第一個比自己大的元素, 然后計算下標之差

很明顯要用到一個單調減(堆疊頭元素最小)的堆疊,通過O(n)的時間復雜度(即遍歷一遍)就能找到每個元素的右邊第一個比它大的元素,本質就是空間換時間,

  1. 為什么是單調減?

    答:因為只有遞減的時候,我們才能得到天數差,如74放入堆疊時,73即可出堆疊,第一天的天數差就得到了,

  2. 怎么計算天數差?

    答:單調堆疊內只存放元素的下標即可,需要數值比較時直接使用 t[i] 即可,

  3. 模板怎么用??

既然已經分析出要用單調堆疊,我們可以直接把三板斧(模板)使出來:

 // 模板
 stack<int> stk;
 for (int i = 0; i < t.size(); i++) {                // 遍歷溫度陣列t
     while (!stk.empty() && t[i] > t[stk.top()]) {   // 出堆疊條件,保持單調減
         stk.pop();
     }
     stk.push(i);                                    // 入堆疊,放入下標
 }

在腦中模擬一下出入堆疊的程序:

  • 堆疊為空,73的下標0入堆疊,堆疊內元素 0

  • 74 > 73,73出堆疊74入堆疊,天數差為1,堆疊內元素 1

  • 75 > 74,74出堆疊75入堆疊,天數差為1,堆疊內元素 2

從第二步就可以看出來,我們需要在堆疊內元素出堆疊前通過下標計算天數差,增加一行即可:

     while (!stk.empty() && t[i] > t[stk.top()]) {   // 出堆疊條件,保持單調減
         res[stk.top()] = i - stk.top();    // 添加計算
         
         stk.pop();
     }

Solution

完整代碼如下,可以嘗試一下,原題鏈接:

 // hrh 8/28 
 class Solution {
 public:
     vector<int> dailyTemperatures(vector<int>& t) {
         vector<int> res(t.size());
         stack<int> stk;     
 ?
         for (int i = 0; i < t.size(); i++) {                // 遍歷
             while (!stk.empty() && t[i] > t[stk.top()]) {   // 出堆疊條件
                 res[stk.top()] = i - stk.top();             // 計算天數差值
                 stk.pop();                                  // 保持單調減
             }
             stk.push(i);                                    // 入堆疊
         }
 ?
         return res;
     }
 };

總結一下解題程序:

  1. 判斷這道題能否用單調堆疊解決
  2. 判斷單調性,給出三板斧
  3. 模擬計算程序,刪改模板得到結果

42. 接雨水

Description

image-20210828161544418

Simulation

思路:

  1. 看圖分析,只有下一個大于等于自己的元素插入才會形成凹槽接到雨水,所以顯而易見,我們應該使用單調堆疊,
  2. 單調性怎么判斷?很明顯,比自己小的可以直接插入,大的插入要讓前面的小元素出堆疊,因此我們需要一個遞減的堆疊(堆疊頂元素最小),
  3. 面積怎么計算?底 ? 高大伙都知道,然后按行計算,下面是分析:

首先明確一下單調堆疊里到底要存什么內容,每個柱的高度?不不不!我們需要下標來計算寬度,而下標又可以直接get到對應的高度,所以只需一個單調堆疊來存盤下標就可以了,

image-20210828161509298

畫了一張圖進行模擬計算程序,一組數[2,1,0,3] 從左到右依次入堆疊:

  • 2入堆疊,堆疊為空,下標i直接入堆疊,堆疊內元素 i
  • 1<2,直接入堆疊,堆疊內元素 i, i+1
  • 0<1,直接入堆疊,堆疊內元素 i, i+1, i+2
  • 3>0,保存0作為基底然后出堆疊,計算凹槽面積:高為1,選擇3與當前堆疊頂元素1之間小的那個(木桶理論,看短的);底為1,3的下標減去1的下標 (i+3) - (i+2) ;總面積+1,繼續判斷 👇
  • 3>1,保存1作為基底然后出堆疊,計算凹槽面積:高為1,因為1作為基底,此時堆疊頂元素為2,所以高為 2-1=1 ,下標計算出底為2;總面積+2,繼續判斷 👇
  • 3>2,2出堆疊,但此時堆疊為空,不需要繼續計算,3終于入堆疊,最后堆疊內元素 i+3
  • 總面積為3

看完模擬程序,相信你已經有了思路,單調減的堆疊,三板斧一整,我們只需要在出堆疊的時候計算面積即可,下面給出完整代碼 🍉🍉🍉

Solution

 // hrh 8/29 
 class Solution {
 public:
     int trap(vector<int>& h) {
         stack<int> stk;    
         int res = 0;
         
         // 三板斧!
         for (int i = 0; i < h.size(); i++) {
             while (!stk.empty() && h[i] >= h[stk.top()]) {
                 int base = h[stk.top()];        // 保存基底然后出堆疊
                 stk.pop();      
                 
                 // 堆疊不空時計算面積
                 if (!stk.empty()) {             
                     int height = min(h[stk.top()], h[i]) - base;
                     int width = i - stk.top() - 1;
                     res += height*width;
                 }
             }
             
             stk.push(i);
         }
 ?
         return res;
     }
 };

84. 柱狀圖中最大的矩形

Description

image-20210828161718263

Simulation

思路分析:

  1. 大眼一瞧,柱狀圖高高低低,計算面積,這不是接雨水嗎?單調堆疊確認!

  2. 判斷單調性?可以看到圖中都是遇到小值需要出堆疊的時候才計算面積,可以確認是遞增的堆疊,也就是堆疊頂元素最大,單調性確定!直接三板斧給出:

    image-20210830221122439

  3. 單調堆疊存入下標計算寬度,根據出堆疊的最小值計算高度(具體思路上篇文章已經詳細給出,在此不贅述)刪改后可得:

for (int i = 0; i < h.size(); i++) {
    
    while (!stk.empty() && h[i] < h[stk.top()]) {	// 出堆疊條件
        int pre = stk.top();	// 保存要出堆疊的元素
        stk.pop();

        if (!stk.empty()) {		// 計算面積
            int height = h[pre];
            int width = i - stk.top() - 1;
            res = max(res, height*width);	// 保留更大的值
        }
    }
    
    stk.push(i);
}

但這樣就足夠了嗎?顯然不行,設想兩種情況:

  1. 輸入兩個元素[2,5],本身遞增可以直接入堆疊,沒有出堆疊怎么計算面積?
  2. 輸入任意一個元素,怎么計算面積?

其實解決方法很簡單,我們只要在陣列前后各加一個0就可以了,0一定是最小元素,在前面加一個0不用擔心堆疊空的情況,每次出堆疊都計算一下面積;沒有出堆疊條件就創造出堆疊條件,所以在陣列后面加一個0,

h.insert(h.begin(), 0);		// 前插一個0
h.push_back(0);			    // 后插一個0

Solution

完整代碼如下:

class Solution {
public:
    int largestRectangleArea(vector<int>& h) {
        stack<int> stk;
        int res = 0;
        h.insert(h.begin(), 0);
        h.push_back(0);

        for (int i = 0; i < h.size(); i++) {
    
            while (!stk.empty() && h[i] < h[stk.top()]) {	// 出堆疊條件
                int pre = stk.top();	// 保存要出堆疊的元素
                stk.pop();

                // 堆疊不會空
                int height = h[pre];
                int width = i - stk.top() - 1;
                res = max(res, height*width);	// 保留更大的值
            }
            
            stk.push(i);
        }
    
        return res;
    }

};

Conclusion

復習一下解題程序:

  1. 判斷這道題能否用單調堆疊解決
  2. 判斷單調性,給出三板斧
  3. 模擬計算程序,刪改模板得到結果

可以看到最大矩形面積這道題跟接雨水雖然相似,但麻煩了許多,特殊值的輸入給我們的解題思路帶來了一定困擾,不過你不能指望Hard題都是套個模板就能AC的,

雖然三板斧很好用,但一些特殊條件的計算仍然是需要你自己的判斷,那么問題來了:怎么提高自己的能力?

我這里有好康的:力扣單調堆疊題庫

刷題!刷題!還是TMD刷題!!!🍗🍗


寫文不易,求個贊 💗💗

可以點個關注互相交流~

我是Mancuoj,更多有趣文章:我的個人主頁

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/296645.html

標籤:其他

上一篇:如何查看ssl證書版本資訊

下一篇:Web前端開發工程師知識體系_18_CSS(六)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more