單調棧 leetcode整理(三)

目錄

  • 42. 接雨水
    • 思路分析
  • 901. 股票價格跨度
    • 思路
  • 581. 最短無序連續子數組
    • 思路一:排序+雙指針
    • 思路二:單調棧
    • 思路三:雙指針(最省時)

42. 接雨水

42. 接雨水
給定 n 個非負整數表示每個寬度為 1 的柱子的高度圖,計算按此排列的柱子,下雨之后能接多少雨水。
在這里插入圖片描述

輸入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
輸出:6
解釋:上面是由數組 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度圖,在這種情況下,可以接 6 個單位的雨水(藍色部分表示雨水)。

示例 2:

輸入:height = [4,2,0,3,2,5] 輸出:9

提示:

n == height.length
0 <= n <= 3 * 10^4
0 <= height[i] <= 10^5

思路分析

由于這一題方法比較多,就專門寫了一個:
https://blog.csdn.net/qq_42604176/article/details/111053090

901. 股票價格跨度

編寫一個 StockSpanner 類,它收集某些股票的每日報價,并返回該股票當日價格的跨度。

今天股票價格的跨度被定義為股票價格小于或等于今天價格的最大連續日數(從今天開始往回數,包括今天)。

例如,如果未來7天股票的價格是 [100, 80, 60, 70, 60, 75, 85],那么股票跨度將是 [1, 1, 1, 2, 1, 4, 6]。
示例:

輸入:[“StockSpanner”,“next”,“next”,“next”,“next”,“next”,“next”,“next”], [[],[100],[80],[60],[70],[60],[75],[85]]
輸出:[null,1,1,1,2,1,4,6]
解釋:
首先,初始化 S = StockSpanner(),然后:
S.next(100) 被調用并返回 1,
S.next(80) 被調用并返回 1,
S.next(60) 被調用并返回 1,
S.next(70) 被調用并返回 2,
S.next(60) 被調用并返回 1,
S.next(75) 被調用并返回 4,
S.next(85) 被調用并返回 6。

注意 (例如) S.next(75) 返回 4,因為截至今天的最后 4 個價格
(包括今天的價格 75) 小于或等于今天的價格。

思路

仍然是單調棧的思路,構造一個單調遞減棧。
1、如果當前棧為空,輸入元素在原數組中的下標壓入棧中。
獲取該元素左邊極大值的坐標,此時棧為空,說明左邊沒有比該元素還小的元素,所以左邊極大值坐標就是不存在,填-1(不能填0)
然后返回長度就是當前元素在原數組中下標 - 左極大值坐標
可以想象一下,如果左邊極大值不存在的時候,我們填入0,而當前輸入元素正好是第0個元素,那么顯然結果就是0 - 0 = 0 ,不符合答案1。
2、如果當前棧不為空,并且棧頂元素小于等于輸入元素。
此時根據題目要求:小于或等于今天價格的最大連續日數,我們必須要找到大于今日價格才能停止尋找,所以仍然需要回撤操作。
直到棧為空或者棧頂元素大于今日價格,才停止回撤。
如果棧為空,說明左邊沒有比該元素還小的元素,所以左邊極大值坐標就是不存在,填-1(不能填0)
如果棧不為空,左極大值坐標就是當前棧頂元素坐標。
最后將今日 - 左極大值日期,就是結果

和之前系列中有的操作還是相似的,例如棧中記錄的不是元素,而是該元素在原數組中的下標。
對于棧頂元素與當前元素的比較,仍然是需要結合題意,列出三種可能:當前元素 < 、 == 、 > st.back(),找到符合題意的出棧標準

class StockSpanner {
private:vector<int> input;vector<int> st;
public:StockSpanner() {}int next(int price) {//輸入一個price,input數組又多了一個元素input.emplace_back(price);//該元素為input數組末尾int now_index = input.size() - 1;//如果此時棧為空,說明它左邊沒有值while(!st.empty() && input[st.back()] <= price){st.pop_back();}//獲取該元素左邊極大值的下標,如果棧為空的話,說明沒有,那么left_max就是-1;如果不為空,返回棧頂int left_max_index;if(st.empty()) left_max_index = -1;else left_max_index = st.back();//當前元素入棧st.push_back(now_index);return (now_index - left_max_index);}
};/*** Your StockSpanner object will be instantiated and called as such:* StockSpanner* obj = new StockSpanner();* int param_1 = obj->next(price);*/

581. 最短無序連續子數組

給定一個整數數組,你需要尋找一個連續的子數組,如果對這個子數組進行升序排序,那么整個數組都會變為升序排序。
你找到的子數組應是最短的,請輸出它的長度。
示例 1:

輸入: [2, 6, 4, 8, 10, 9, 15]
輸出: 5
解釋: 你只需要對 [6, 4, 8, 10, 9] 進行升序排序,那么整個表都會變為升序排序。

說明 :

輸入的數組長度范圍在 [1, 10,000]。
輸入的數組可能包含重復元素 ,所以升序的意思是<=。

思路一:排序+雙指針

先排序,然后將排序后的數組與原數組進行比對(從左到右、從右到左)。
找到左右邊界,然后最后的結果就是左右邊界差值+1.
當然還要考慮特殊情況:原數組本身是單調遞增或遞減的,這樣我們就不能對左右邊界進行更新。
但是我們知道單調的結果:無非是0(單調遞增不需要重新排序),和nums.size()(單調遞減需要將整個數組都排序).

class Solution {
public:int findUnsortedSubarray(vector<int>& nums) {vector<int> _new = nums;sort(_new.begin(),_new.end());int left_index = -1;int right_index = -1;//雙指針left、right,從兩邊向中間遍歷for(int left = 0; left < nums.size(); left++){if(nums[left] != _new[left]){left_index = left;break;}}for(int right = nums.size() - 1; right >= 0; right--){if(nums[right] != _new[right]){right_index = right;break;}}//如果是單調遞增,不需要修改,返回0if(left_index == -1) return 0;//如果是單調遞減,返回整個長度if(right_index == -1) return nums.size();return (right_index - left_index + 1);}
};

思路二:單調棧

背后的思想仍然是選擇排序,我們需要找到無序子數組中最小元素和最大元素分別對應的正確位置。
來求我們需要的無序子數組的邊界。
使用棧,從頭遍歷nums數組:
1、如果遇到的數組大小一直升序的,我們就不斷把對應的下標壓入棧中,目的:這些元素目前都是出于正確的位置上
2、一旦當前數字比棧頂元素小,那么我們知道nums[j]一定不在正確的位子上
3、既然這樣,我們就需要找到nums[j]的正確位置:
不斷將棧頂元素彈出,知道棧頂元素比nums[j],假設此刻棧頂元素對應的下標是k,那么我們知道nums[j]的正確下標應該是k+1
4、重復上述過程,直到遍歷完整個數組,這樣我們可以找到最小的k,它也是無序子數組的左邊界。
5、類似的,我們逆序遍歷一遍nums數組來找到無序子數組的右邊界。這一次我們將降序的元素壓入棧中。
6、如果遇到一個升序的元素,不斷將棧頂元素彈出,直到找到一個更大的元素,以此找到無序子數組的右邊界

class Solution {
public:int findUnsortedSubarray(vector<int>& nums) {vector<int> st;int left = nums.size() - 1;int right = 0;for(int i = 0; i < nums.size(); i++){while(!st.empty() && nums[i] < nums[st.back()]){left = min(left,st.back()); st.pop_back();}st.emplace_back(i);}st.clear();for(int i = nums.size() - 1; i >= 0; i--){while(!st.empty() && nums[i] > nums[st.back()]){right = max(right,st.back()); st.pop_back();}st.emplace_back(i);}return right - left > 0 ? right - left + 1 : 0;}
};

思路三:雙指針(最省時)

這一題的雙指針解法和接雨水的雙指針思想有一定相似性:
leetcode 42. 接雨水 思考分析(暴力、動態規劃、雙指針、單調棧)
我們要做的是,找到無序數組的上下界。
運用到本題,就是下面兩個想法:
https://leetcode-cn.com/problems/shortest-unsorted-continuous-subarray/solution/shi-jian-chao-guo-100de-javajie-fa-by-zackqf/
https://leetcode-cn.com/problems/shortest-unsorted-continuous-subarray/solution/jian-dan-zhi-guan-de-shuang-zhi-zhen-fa-by-sillywo/
無序子數組中最小元素的正確位置可以決定左邊界,最大元素的正確位置可以決定右邊界。
尋找右邊界:
從左往右遍歷,用max記錄遍歷過的最大值,如果max大于當前nums[i],說明nums[i]的位子不正確,屬于需要排序的數組,所以右邊界就需要更新為i
如果nums[i]大于max更新max,繼續往右檢查,是否有元素比更新之后的max要小;最終可以找到需要排序的數組的右邊界,右邊界之后的元素都大于max。
尋找左邊界:
從右向左遍歷,yongmin記錄當前遍歷過的最小值,如果min小于當前nums[i],說明nums[i]的位子不正確,屬于需要排序的數組,所以更新左邊界
如果nums[i]小于min更新min,繼續往左檢查,是否有元素比更新之后的min要大,最終可以找到需要排序的數組的左邊界,左邊界之前的元素都小于min

class Solution {
public:int findUnsortedSubarray(vector<int>& nums) {//特判int n = nums.size();if (n <= 1) {return 0;}//從右到左找下界,從左到右找上界int left = n - 2, right = 1; int curMin = nums[n - 1], curMax = nums[0];int up = 0, down = 1;//升序時移動 curMin 和 curMax//逆序時移動 down 和 up//不論順序如何,雙指針 left 和 rigt 一直保持移動while (left >=0 && right < n) {if (nums[left] > curMin){down = left;}else {curMin = nums[left];}left--;if (nums[right] < curMax) {up = right;}else {curMax = nums[right];}right++;}return up - down + 1;}
};

單調棧暫時就刷到這兒,接下來繼續刷雙指針的題目吧。

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

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

相關文章

python 摳圖 鋸齒_Python | 繪圖中的抗鋸齒

python 摳圖 鋸齒Antialiasing is another important feature of Matplotlib and in this article, we will review how to use this functionality. pyplot.antialiased() is an inbuilt function in matplotlib.pyplot which performs our required operation. 抗鋸齒是Matpl…

apk 反編譯

引用&#xff1a;http://code.google.com/p/dex2jar/issues/detail?id20 最新版:dex2jar http://code.google.com/p/dex2jar/downloads/list 錯誤&#xff1a;http://code.google.com/p/dex2jar/issues/detail?id20 這段時間在學Android應用開發&#xff0c;在想既然是用Jav…

OpenDiscussion_DataDrivenDesign

本文源于公司內部技術交流&#xff0c;如有不當之處&#xff0c;還請指正。 Content&#xff1a; 1. What is Data-driven design?2. WPF revolution.3. More about ObservableCollection.4. Question.1. What is Data-driven design?Data-driven design: is a design of usi…

十三、Loss Functions

一、Loss Functions損失函數 損失函數的作用&#xff1a; 1&#xff0c;損失函數就是實際輸出值和目標值之間的差 2&#xff0c;由這個差便可以通過反向傳播對之后的數據進行更新 Loss Functions官網給的API 里面由很多種損失函數&#xff0c;不同的損失函數有其不同的用途及表…

leetcode 滑動窗口小結 (一)

目錄小結以及代碼框架76. 最小覆蓋子串滑動窗口代碼以及注釋567. 字符串的排列滑動窗口438. 找到字符串中所有字母異位詞3. 無重復字符的最長子串化簡框架reference小結以及代碼框架 滑動窗口技巧屬于雙指針技巧。 該算法的思路為維護一個窗口&#xff0c;不斷滑動&#xff0c…

linux命令行界面_Linux中的命令行界面

linux命令行界面If you are like most people, you are probably most familiar with using a Graphical User Interface (GUI) to control your computer. Introduced to the masses by Apple on the Macintosh computer and popularized by Microsoft, a GUI provides an eas…

一道小小面試題的細節分析

一道小小面試題的細節分析 今天突然想到以前遇到的一個問題&#xff0c;題目如下&#xff08;可能絕大多數人都遇到過&#xff09;&#xff1a; 1 class A2 {3 public A()4 {5 PrintFields();6 }7 public virtual void Pr…

十四、OPTIM

一、torch.optim torch.optim.Optimizer(params, defaults)優化器官網說明 由官網給的使用說明打開看出來優化器實驗步驟&#xff1a; ①構造選擇優化器 例如采用隨機梯度下降優化器SGD torch.optim.SGD(beyond.parameters(),lr0.01)&#xff0c;放入beyond模型的參數param…

Windows下運行jekyll,編碼已不再是問題

很久沒更新jekyll了&#xff0c;所以好奇著去官網看了下更新記錄&#xff0c;發現如下更新條目&#xff08;版本1.3.0/2013-11-04發布&#xff09;&#xff1a; Add encoding configuration option (#1449)之前在windows下安裝jekyll運行編寫的代碼時&#xff0c;如果有中文&am…

leetcode 滑動窗口小結 (二)

目錄424. 替換后的最長重復字符思考分析1優化1004. 最大連續1的個數 III友情提醒方法1&#xff0c;基于當前最大頻數方法2&#xff0c;基于歷史最大頻數424. 替換后的最長重復字符 https://leetcode-cn.com/problems/longest-repeating-character-replacement/ 給你一個僅由大…

軟件故障_一些主要的軟件故障

軟件故障The need for software engineering was realized by the software industry after some of its major failures. Some of these failures are listed below, 在經歷了一些重大失敗之后&#xff0c;軟件行業意識到了對軟件工程的需求 。 下面列出了其中一些故障&#x…

十五、修改VGG16網絡來適應自己的需求

一、VGG-16 VGG-16神經網絡是所訓練的數據集為ImageNet ImageNet數據集中驗證集和測試集一萬五千張&#xff0c;有一千個類別 二、加載VGG-16神經網絡模型 VGG16模型使用說明 torchvision.models.vgg16(pretrainedFalse) 其中參數pretrained表示是否下載已經通過ImageNet數…

leetcode 滑動窗口小結 (三)

目錄978. 最長湍流子數組題目思路分析以及代碼1052. 愛生氣的書店老板題目思考分析與初步代碼優化思路以及優化代碼1208. 盡可能使字符串相等題目思考分析以及代碼978. 最長湍流子數組 https://leetcode-cn.com/problems/longest-turbulent-subarray/ 題目 當 A 的子數組 A[…

JAVA多線程學習3--線程一些方法

一、通過sleep方法睡眠 在指定的毫秒數內讓當前正在執行的線程休眠&#xff08;暫停執行&#xff09;。該線程不丟失任何監視器的所屬權。 二、線程優先級 線程具有優先級&#xff0c;范圍為1-10。 MAX_PRIORITY線程可以具有的最高優先級。int類型&#xff0c;值為10. MIN_PRIO…

mcq 隊列_MCQ | 量子密碼學

mcq 隊列1) Which possible Attacks in Quantum Cryptography can take place? 1)量子密碼術中可能發生哪些攻擊&#xff1f; Possible Attacks in Quantum Cryptography and Birthday Attack 量子密碼術和生日攻擊的可能攻擊 Birthday attack and Boomerang attack 生日襲擊…

《inside the c++ object model》讀書筆記 之一:對象

關于對象 ...引子:在C語言中,"數據"和"處理數據的操作(函數)"是分開來聲明的,語言本身并沒有支持"數據和函數"之間關聯性,這種程序成為"程序性的",由一組"分布在各個一功能為向導的函數中"的算法驅動,他們處理的是共同的外部…

十六、保存和加載自己所搭建的網絡模型

一、保存自己搭建的模型方法一 例如&#xff1a;基于VGG16網絡模型架構的基礎上加上了一層線性層&#xff0c;最后的輸出為10類 torch.save(objmodule,f"path")&#xff0c;傳入需要保存的模型名稱以及要保存的路徑位置 保存模型結構和模型的參數&#xff0c;保存文…

uC/OS-II OS_TASK.C中有關任務管理的函數

函數大致用途 OS_TASK.C是uC/OS-II有關任務管理的文件&#xff0c;它定義了一些函數&#xff1a;建立任務、刪除任務、改變任務的優先級、掛起和恢復任務&#xff0c;以及獲取有關任務的信息。 函數用途OSTaskCreate()建立任務OSTaskCreateExt()擴展建立任務OSTaskStkChk()堆…

windows下寫的腳本,在linux下執行失敗

Windows中的換行符為CRLF, 即正則表達式的rn(ASCII碼為13和10), 而Unix(或Linux)換行符為LF, 即正則表達式的n. 在Windows和Linux下協同工作的時候, 往往這個細小的差別就導致問題, 如 1)Windows下寫的Shell腳本, 在Linux下運行時往往出現rn是無效參數, 不能執行; 2)vi 等編器下…

Scala中的do ... while循環

做...在Scala循環 (do...while loop in Scala) do...while loop in Scala is used to run a block of code multiple numbers of time. The number of executions is defined by an exit condition. If this condition is TRUE the code will run otherwise it runs the first …