从栈底元素到栈顶元素呈单调递增或单调递减,栈内序列满足单调性的栈
(1)当新元素在单调性上优于栈顶时(单增栈新元素比栈顶大,单减栈新元素比栈顶小),压栈,栈深+1;
(2)当新元素在单调性与栈顶相同(新元素于栈顶相同)或劣于栈顶时(单增栈新元素比栈顶小,单减栈新元素比栈顶大),弹栈,栈深-1;
在一个数组arr[N]中,给定一个数num,分别求解各arr[i]左边比num大的距离其最近的和右边比num大的距离其最近的数,使得其时间复杂度为O(N)(优于暴力解法的O(n*n))。
单调栈模板代码
1.使用数组进行模拟单调递增栈:
cin>>nums[i]
int s[maxn],tot=0;
for(int i=0;i<maxn;i++){
while(tot>=1&&s[tot-1]>=nums[i]){
tot--;
}
if(tot) cout<<stac[tot-1]<<' ';
else cout<<-1<<' ';
s[tot++]=nums[i];
}
2.使用栈进行模拟单调递增栈:
cin>>nums[i]
stack<int> s;
for(int i=0;i<n;i++){
while(!s.empty()&&s.top()>=nums[i]){
s.pop();
}
if(!s.empty()) cout<<s.top()<<' ';
else cout<<-1<<' ';
s.push(nums[i]);
}
在这里插入代码片
**题目:**力扣 84. 柱状图中最大的矩形
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。
示例:
输入: [2,1,5,6,2,3]
输出: 10
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/largest-rectangle-in-histogram
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
如图是一系列的离散的数列,若一A点为高求最大的矩形,需找到左与右第一个比它小的数据点,以二者距离为宽乘以高可得面积,暴力解法很容易就可以得出,但时间复杂度为n^2。为提高算法效率,引入单调递增栈的数据结构,其特性为栈内的元素以出栈方向严格单调递增,利用这一特性可以很好的在栈顶为A点入栈新点B不用出栈时(A点的压栈方向的下一个元素为点C),快速的确定A点左与右第一个比它小的数据点分别为点C与点A,此时算法复杂度为构造单调栈的时间复杂度n,大大提升了算法效率。
具体代码如下:
class Solution {
public://使用单调栈的思想
int largestRectangleArea(vector<int>& heights) {
stack<int> s;
int retmax=0;
int len=heights.size(); //递增单调栈 (L,R)开区间
for(int i=0;i<len;i++){ //将出栈的元素作为高计算,L为该元素的栈下元素,R为将要入栈的元素;
while(!s.empty()&&heights[s.top()]>=heights[i]){
int h=s.top();
s.pop();
int l;
if(s.empty()) l=-1;
else l=s.top();
retmax=max(retmax,(i-l-1)*heights[h]);
}
s.push(i);
}
while(!s.empty()){//将栈内的元素作为高计算,L为该元素的栈下元素,R为数组长度;
int h=s.top();
s.pop();
int l;
if(s.empty()) l=-1;
else l=s.top();
retmax=max(retmax,(len-l-1)*heights[h]);
}
return retmax; //此时全部元素分为二部分计算完毕
}
};
题目: 85. 最大矩形
给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。
示例:
输入:matrix = [[“1”,“0”,“1”,“0”,“0”],[“1”,“0”,“1”,“1”,“1”],[“1”,“1”,“1”,“1”,“1”],[“1”,“0”,“0”,“1”,“0”]]
输出:6
解释:最大矩形如上图所示。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximal-rectangle
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
由第一题可以启发到,该题是在找一个最大矩阵,最大矩阵由高和宽组成,与第一题类似,但增加了多行,以示例为例,以第一行底构建矩阵的高度数组为10100,第二行为20211,第三行为31322,第四行为30030;题目要求寻找最大,那么简单的方法是遍历所有可能的矩形比较得最大,那么组合的方法为底与高的组合,底可以是每一行,底确定了那么高也就很好确定,采用题目一的方法分别对以四行为底的矩阵进行更新最大矩阵。时间复杂度为y*x.
具体代码如下:
class Solution {
public:
int fun(vector<int> nums){ //根据高度矩阵,计算最大矩形,方法是引入单调栈,更新nums[i]为高的最大矩阵
int len=nums.size();
stack<int> s;
int ret=0;
for(int i=0;i<len;i++){
while(!s.empty()&&nums[s.top()]>=nums[i]){
int r=i;
int h=s.top();
s.pop();
int l=s.empty()?-1:s.top();
ret=max(ret,(r-l-1)*nums[h]);
}
s.push(i);
}
while(!s.empty()){
int r=len;
int h=s.top();
s.pop();
int l=s.empty()?-1:s.top();
ret=max(ret,(r-l-1)*nums[h]);
}
return ret;
}
int maximalRectangle(vector<vector<char>>& matrix) {
int y=matrix.size();
if(y==0) return 0;
int x=matrix[0].size();
vector<int> num(x,0);
int retmax=0;
for(int i=0;i<y;i++){ //依次换行作为矩形的底
for(int j=0;j<x;j++){ //更新高度数组信息
if(matrix[i][j]=='0') num[j]=0;
else num[j]++;
}
retmax=max(retmax,fun(num));//更新最大值结果
}
return retmax;
}
};