单调不减序列查询第一个大于等于_[力扣84,85] 单调栈
題目鏈接
84. 柱狀圖中最大的矩形
85. 最大矩形
題目描述-84
給定 n 個(gè)非負(fù)整數(shù),用來表示柱狀圖中各個(gè)柱子的高度。每個(gè)柱子彼此相鄰,且寬度為 1 。
求在該柱狀圖中,能夠勾勒出來的矩形的最大面積。
樣例-84
輸入: [2,1,5,6,2,3]輸出: 10題目描述-85
給定一個(gè)僅包含 0 和 1 的二維二進(jìn)制矩陣,找出只包含 1 的最大矩形,并返回其面積。
樣例-85
輸入:[
["1","0","1","0","0"],
["1","0","1","1","1"],
["1","1","1","1","1"],
["1","0","0","1","0"]
]
輸出: 6
本題是要找到兩側(cè)第一個(gè)比它小的數(shù)的位置:找到每個(gè)柱形條左邊和右邊最近的比自己低的矩形條,然后用寬度乘高度,得到一個(gè)備選答案。這是單調(diào)棧的典型場景。
單調(diào)棧的核心使用場景:攤銷O(1)地獲得所有位置上兩側(cè)第一個(gè)比它大/小的數(shù)的位置
單調(diào)棧其它題目列表:
907. 子數(shù)組的最小值之和
739. 每日溫度
42. 接雨水
456. 132模式
注:驗(yàn)證前序遍歷序列是否為某個(gè)二叉搜索樹的問題,本質(zhì)上也是 132 模式的問題,如果前序遍歷序列不含 231 模式的子序列,則它是二叉搜索樹,依然用單調(diào)棧解。力扣上也有對應(yīng)題:255. 驗(yàn)證前序遍歷序列二叉搜索樹
496. 下一個(gè)更大元素 I
1019. 鏈表中的下一個(gè)更大節(jié)點(diǎn)
算法:單調(diào)棧
維護(hù)一個(gè)單調(diào)不減的棧,保存當(dāng)前枚舉元素 cur 左側(cè)小于等于 cur 的元素的下標(biāo),其中棧頂離cur 最近,它是 cur 左側(cè)第一個(gè)比它小的元素的位置。
枚舉數(shù)組所有下標(biāo) j,把所有大于 nums[j] 的棧頂都彈出,直到棧頂小于等于 nums[j],然后將 j 壓入(所有下標(biāo)都會(huì)壓入),當(dāng)前枚舉的 j 就處理完了。答案在出棧時(shí)更新,出棧元素為 cur
cur = st.top(); st.pop();此時(shí)對于已經(jīng)彈出的 cur,當(dāng)前的棧頂是 cur 左側(cè)第一個(gè)小于等于 cur 的,nums[j] 是 cur 右側(cè)第一個(gè)大于 cur 的。cur 對應(yīng)的矩形寬度為
w = j - st.top() - 1;當(dāng)棧頂有連續(xù)的幾個(gè)值相等的下標(biāo)時(shí),最后一個(gè)彈出的 cur 會(huì)把左側(cè)第一個(gè)小于 cur 的下標(biāo)取到,先彈出的取到的不是左側(cè)第一個(gè)小于 cur 的,只是第一個(gè)小于等于 cur的,這在此題不影響,但如果要返回每個(gè)位置能取到的最大矩形,則需要額外處理先彈出的幾個(gè)下標(biāo)。
棧底始終放一個(gè) -1 處理 nums[j] 比棧里所有元素都小的情況。
每個(gè)元素都要進(jìn)棧一次出棧一次,總時(shí)間復(fù)雜度 O(N)
對于第85題,M * N 的矩陣,一行一行地考慮,對于第 i 行,矩陣的第 0 到第 i 行可以視為一個(gè)直方圖,然后照搬 84 的做法求該直方圖上的最大矩形。一共有 M 個(gè)直方圖,總時(shí)間復(fù)雜度 O(MN)。
代碼-84(c++)
class Solution { public:int largestRectangleArea(vector<int>& heights) {if(heights.empty()) return 0;int n = heights.size();stack<int> st({-1});int result = 0;for(int i = 0; i < n; ++i){if(st.top() == -1 || heights[st.top()] <= heights[i])st.push(i);else{while(st.top() != -1 && heights[st.top()] > heights[i]){int index = st.top();st.pop();int w = i - st.top() - 1;int area = w * heights[index];result = max(result, area);}st.push(i);}}while(st.top() != -1){int index = st.top();st.pop();int w = n - st.top() - 1;int area = w * heights[index];result = max(result, area);}return result;} };代碼-85(c++)
class Solution { public:int maximalRectangle(vector<vector<char>>& matrix) {if(matrix.empty()) return 0;int n = matrix.size(), m = matrix[0].size();vector<int> heights(m, 0);int result = 0;for(int i = 0; i < n; ++i){_get_geights(matrix, heights, i);int result_i = _max_rec_hist(heights);result = max(result, result_i);}return result;}private:void _get_geights(vector<vector<char> >& matrix, vector<int>& heights, int i){int m = matrix[0].size();for(int j = 0; j < m; ++j){int cnt = 0;int h = i;while(h >= 0 && matrix[h][j] == '1'){++cnt;--h;}heights[j] = cnt;}}int _max_rec_hist(vector<int>& heights){int m = heights.size();stack<int> st;st.push(-1);int result = 0;for(int j = 0; j < m; ++j){while(st.top() != -1 && heights[st.top()] > heights[j]){int h = heights[st.top()];st.pop();int l = st.top();int w = j - l - 1;result = max(result, h * w);}st.push(j);}while(st.top() != -1){int h = heights[st.top()];st.pop();int l = st.top();int w = m - l - 1;result = max(result, w * h);}return result;} };總結(jié)
以上是生活随笔為你收集整理的单调不减序列查询第一个大于等于_[力扣84,85] 单调栈的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手机耗电统计app_教你 6 招,解决
- 下一篇: chrome webdriver_网络爬