女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

單調(diào)棧解題模板如何秒殺三道算法題

jf_78858299 ? 來源:labuladong ? 作者:labuladong ? 2023-04-19 10:52 ? 次閱讀

單調(diào)棧實(shí)際上就是棧,只是利用了一些巧妙的邏輯,使得 每次新元素入棧后,棧內(nèi)的元素都保持有序 (單調(diào)遞增或單調(diào)遞減)。

本文就通過幾道算法題來看看單調(diào)棧模板的使用。

單調(diào)棧模板

首先,看一下 Next Greater Number 的原始問題,這是力扣第 496 題「下一個更大元素 I」:

給你一個數(shù)組,返回一個等長的數(shù)組,對應(yīng)索引存儲著下一個更大元素,如果沒有更大的元素,就存 -1。

函數(shù)簽名如下:

vector<int> nextGreaterElement(vector<int>& nums);

比如說,輸入一個數(shù)組nums = [2,1,2,4,3],你返回?cái)?shù)組[4,2,4,-1,-1]。

解釋:第一個 2 后面比 2 大的數(shù)是 4; 1 后面比 1 大的數(shù)是 2;第二個 2 后面比 2 大的數(shù)是 4; 4 后面沒有比 4 大的數(shù),填 -1;3 后面沒有比 3 大的數(shù),填 -1。

這道題的暴力解法很好想到,就是對每個元素后面都進(jìn)行掃描,找到第一個更大的元素就行了。但是暴力解法的時間復(fù)雜度是O(n^2)。

這個問題可以這樣抽象思考:把數(shù)組的元素想象成并列站立的人,元素大小想象成人的身高。這些人面對你站成一列,如何求元素「2」的 Next Greater Number 呢?很簡單,如果能夠看到元素「2」,那么他后面可見的第一個人就是「2」的 Next Greater Number,因?yàn)楸取?」小的元素身高不夠,都被「2」擋住了,第一個露出來的就是答案。

圖片

這個情景很好理解吧?帶著這個抽象的情景,先來看下代碼。

vector<int> nextGreaterElement(vector<int>& nums) {
    vector<int> res(nums.size()); // 存放答案的數(shù)組
    stack<int> s;
    // 倒著往棧里放
    for (int i = nums.size() - 1; i >= 0; i--) {
        // 判定個子高矮
        while (!s.empty() && s.top() <= nums[i]) {
            // 矮個起開,反正也被擋著了。。。
            s.pop();
        }
        // nums[i] 身后的 next great number
        res[i] = s.empty() ? -1 : s.top();
        // 
        s.push(nums[i]);
    }
    return res;
}

這就是單調(diào)隊(duì)列解決問題的模板。for 循環(huán)要從后往前掃描元素,因?yàn)槲覀兘柚氖菞5慕Y(jié)構(gòu),倒著入棧,其實(shí)是正著出棧。while 循環(huán)是把兩個「個子高」元素之間的元素排除,因?yàn)樗麄兊拇嬖跊]有意義,前面擋著個「更高」的元素,所以他們不可能被作為后續(xù)進(jìn)來的元素的 Next Great Number 了。

這個算法的時間復(fù)雜度不是那么直觀,如果你看到 for 循環(huán)嵌套 while 循環(huán),可能認(rèn)為這個算法的復(fù)雜度也是O(n^2),但是實(shí)際上這個算法的復(fù)雜度只有O(n)

分析它的時間復(fù)雜度,要從整體來看:總共有n個元素,每個元素都被push入棧了一次,而最多會被pop一次,沒有任何冗余操作。所以總的計(jì)算規(guī)模是和元素規(guī)模n成正比的,也就是O(n)的復(fù)雜度。

問題變形

單調(diào)棧的使用技巧差不多了,來一個簡單的變形,力扣第 1118 題「一月有多少天」:

給你一個數(shù)組T,這個數(shù)組存放的是近幾天的天氣氣溫,你返回一個等長的數(shù)組,計(jì)算: 對于每一天,你還要至少等多少天才能等到一個更暖和的氣溫;如果等不到那一天,填 0

函數(shù)簽名如下:

vector<int> dailyTemperatures(vector<int>& T);

比如說給你輸入T = [73,74,75,71,69,76],你返回[1,1,3,2,1,0]。

解釋:第一天 73 華氏度,第二天 74 華氏度,比 73 大,所以對于第一天,只要等一天就能等到一個更暖和的氣溫,后面的同理。

這個問題本質(zhì)上也是找 Next Greater Number,只不過現(xiàn)在不是問你 Next Greater Number 是多少,而是問你當(dāng)前距離 Next Greater Number 的距離而已。

相同的思路,直接調(diào)用單調(diào)棧的算法模板,稍作改動就可以,直接上代碼吧:

vector<int> dailyTemperatures(vector<int>& T) {
    vector<int> res(T.size());
    // 這里放元素索引,而不是元素
    stack<int> s; 
    /* 單調(diào)棧模板 */
    for (int i = T.size() - 1; i >= 0; i--) {
        while (!s.empty() && T[s.top()] <= T[i]) {
            s.pop();
        }
        // 得到索引間距
        res[i] = s.empty() ? 0 : (s.top() - i); 
        // 將索引入棧,而不是元素
        s.push(i); 
    }
    return res;
}

單調(diào)棧講解完畢,下面開始另一個重點(diǎn):如何處理「循環(huán)數(shù)組」。

如何處理環(huán)形數(shù)組

同樣是 Next Greater Number,現(xiàn)在假設(shè)給你的數(shù)組是個環(huán)形的,如何處理?力扣第 503 題「下一個更大元素 II」就是這個問題:

比如輸入一個數(shù)組[2,1,2,4,3],你返回?cái)?shù)組[4,2,4,-1,4]。擁有了環(huán)形屬性, 最后一個元素 3 繞了一圈后找到了比自己大的元素 4 。

一般是通過 % 運(yùn)算符求模(余數(shù)),來獲得環(huán)形特效:

int[] arr = {1,2,3,4,5};
int n = arr.length, index = 0;
while (true) {
    print(arr[index % n]);
    index++;
}

這個問題肯定還是要用單調(diào)棧的解題模板,但難點(diǎn)在于,比如輸入是[2,1,2,4,3],對于最后一個元素 3,如何找到元素 4 作為 Next Greater Number。

對于這種需求,常用套路就是將數(shù)組長度翻倍

圖片

這樣,元素 3 就可以找到元素 4 作為 Next Greater Number 了,而且其他的元素都可以被正確地計(jì)算。

有了思路,最簡單的實(shí)現(xiàn)方式當(dāng)然可以把這個雙倍長度的數(shù)組構(gòu)造出來,然后套用算法模板。但是, 我們可以不用構(gòu)造新數(shù)組,而是利用循環(huán)數(shù)組的技巧來模擬數(shù)組長度翻倍的效果 。

直接看代碼吧:

vector<int> nextGreaterElements(vector<int>& nums) {
    int n = nums.size();
    vector<int> res(n);
    stack<int> s;
    // 假裝這個數(shù)組長度翻倍了
    for (int i = 2 * n - 1; i >= 0; i--) {
        // 索引要求模,其他的和模板一樣
        while (!s.empty() && s.top() <= nums[i % n])
            s.pop();
        res[i % n] = s.empty() ? -1 : s.top();
        s.push(nums[i % n]);
    }
    return res;
}

這樣,就可以巧妙解決環(huán)形數(shù)組的問題,時間復(fù)雜度O(N)

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 算法
    +關(guān)注

    關(guān)注

    23

    文章

    4699

    瀏覽量

    94753
  • 數(shù)組
    +關(guān)注

    關(guān)注

    1

    文章

    419

    瀏覽量

    26373
收藏 人收藏

    評論

    相關(guān)推薦
    熱點(diǎn)推薦

    什么是模板匹配?模板匹配的原理講解 圖像處理與模板匹配算法

    目標(biāo)。模板就是我們已知的在圖中要找的目標(biāo),且該目標(biāo)同模板有相同的尺寸、方向和圖像,通過一定的算法可以在圖中找到目標(biāo),確定其坐標(biāo)位置。 二:模板匹配的原理 用通俗的語言來解釋
    的頭像 發(fā)表于 05-05 09:25 ?3.6w次閱讀
    什么是<b class='flag-5'>模板</b>匹配?<b class='flag-5'>模板</b>匹配的原理講解 圖像處理與<b class='flag-5'>模板</b>匹配<b class='flag-5'>算法</b>

    嵌入式開發(fā)經(jīng)典算法逆序

    不借助其他數(shù)據(jù)結(jié)構(gòu),如何實(shí)現(xiàn)的逆序?這是一非常經(jīng)典的算法筆試題。
    發(fā)表于 08-06 17:10 ?483次閱讀

    單片機(jī)8031、四、五。一10元

    單片機(jī)8031、四、五。一10元,直接發(fā)我qq840921270 ,會給第一個采用
    發(fā)表于 04-16 17:02

    2018年全國大學(xué)生數(shù)學(xué)建模競賽B題解題程序----廣西大學(xué) 69隊(duì)

    ......星期四晚上拿到賽,按照慣例應(yīng)該是請假全身心投入比賽,呃呃...然而并沒有請假...大致看了A、B兩,A題目短...估計(jì)坑多...于是選了B。。B
    發(fā)表于 05-31 12:15

    自動控制原理解題

    自動控制原理解題典是根據(jù)高等工科院校自動控制原理教學(xué)大綱的基本要求編寫的,書中例題涵蓋了經(jīng)典控制理論和線性系統(tǒng)狀態(tài)空間分析的基本內(nèi)容。全書共分九章,每章均
    發(fā)表于 07-11 09:01 ?93次下載
    自動控制原理<b class='flag-5'>解題</b><b class='flag-5'>題</b>典

    模板方法模式在回溯算法中的應(yīng)用

    描述了模板方法模式及回溯算法模板方法模式的Java 語言實(shí)現(xiàn),該實(shí)現(xiàn)使得回溯算法的實(shí)現(xiàn)達(dá)到了可擴(kuò)展性、靈活性和可插入性個目標(biāo),提高了
    發(fā)表于 01-15 16:48 ?20次下載

    模板方法模式在回溯算法中的應(yīng)用

    描述了模板方法模式及回溯算法模板方法模式的Java 語言實(shí)現(xiàn),該實(shí)現(xiàn)使得回溯算法的實(shí)現(xiàn)達(dá)到了可擴(kuò)展性、靈活性和可插入性個目標(biāo),提高了
    發(fā)表于 01-15 16:51 ?0次下載

    國內(nèi)開發(fā)者在GitHub上開源LeetCode刷模板

    為了更好的與開發(fā)者分享自己的刷技巧,greyireland 在 GitHub 上開源了一套 LeetCode 刷模板:algorithm-pattern,主要記錄他通過各種刷文章
    的頭像 發(fā)表于 07-01 15:03 ?2002次閱讀
    國內(nèi)開發(fā)者在GitHub上開源LeetCode刷<b class='flag-5'>題</b><b class='flag-5'>模板</b>!

    快來,我出個算法給你做做

    考大家一個算法 責(zé)任編輯:xj 原文標(biāo)題:考大家一個算法 文章出處:【微信公眾號:算法與數(shù)據(jù)結(jié)構(gòu)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
    的頭像 發(fā)表于 10-10 16:55 ?1522次閱讀

    一篇文章秒殺區(qū)間相關(guān)的問題

    經(jīng)常有讀者問區(qū)間相關(guān)的問題,今天寫一篇文章,秒殺區(qū)間相關(guān)的問題。 所謂區(qū)間問題,就是線段問題,讓你合并所有線段、找出線段的交集等等。主要有兩個技巧: 1、排序。常見的排序方法就是按照區(qū)間起點(diǎn)排序
    的頭像 發(fā)表于 10-12 14:54 ?2091次閱讀
    一篇文章<b class='flag-5'>秒殺</b><b class='flag-5'>三</b><b class='flag-5'>道</b>區(qū)間相關(guān)的問題

    深入淺出了解單調(diào)單調(diào)隊(duì)列

    袁廚攜袁記菜館全體工作人員祝大家在新的一年,健健康康,開開心心。發(fā)量暴增,錢包超大。 哎,元旦假期結(jié)束了,又要繼續(xù)搬磚了,我們接著做題吧,今天我們好好說說單調(diào)單調(diào)隊(duì)列。其實(shí)很容易理解,單調(diào)
    的頭像 發(fā)表于 02-02 10:18 ?1658次閱讀
    深入淺出了解<b class='flag-5'>單調(diào)</b><b class='flag-5'>棧</b>和<b class='flag-5'>單調(diào)</b>隊(duì)列

    如何用DFS算法秒殺島嶼系列問題

    DFS/BFS 算法遍歷二維數(shù)組 。 本文主要來講解如何用 DFS 算法秒殺島嶼系列問題,不過用 BFS 算法的核心思路是完全一樣的,無非就是把 DFS 改寫成 BFS 而已。 那
    的頭像 發(fā)表于 11-16 17:13 ?1937次閱讀
    如何用DFS<b class='flag-5'>算法</b>來<b class='flag-5'>秒殺</b>島嶼系列問題

    DFS算法秒殺島嶼系列問題

    本文主要來講解如何用 DFS 算法秒殺島嶼系列問題,不過用 BFS 算法的核心思路是完全一樣的,無非就是把 DFS 改寫成 BFS 而已。
    的頭像 發(fā)表于 04-19 10:39 ?782次閱讀
    DFS<b class='flag-5'>算法</b><b class='flag-5'>秒殺</b>五<b class='flag-5'>道</b>島嶼系列問題

    數(shù)據(jù)結(jié)構(gòu)解決滑動窗口問題

    前文用 [單調(diào)解決算法問題]介紹了單調(diào)這種特
    的頭像 發(fā)表于 04-19 10:50 ?885次閱讀
    數(shù)據(jù)結(jié)構(gòu)解決滑動窗口問題

    滑動窗口算法解決子串問題教程

    難但太復(fù)雜,所以本文只選擇點(diǎn)贊最高,較為經(jīng)典的,最能夠講明白的來講解。第一題為了讓讀者掌握算法模板,篇幅相對長,后兩
    的頭像 發(fā)表于 04-19 11:06 ?991次閱讀
    滑動窗口<b class='flag-5'>算法</b>解決子串問題教程