单调栈的作用
就是用一个栈来记录我们遍历过的元素
单调栈里存放元素下标i就可以了,如果要使用对应元素,直接T[i]就可以获取到
从栈头到栈尾-递增的话-栈里要加入一个元素i的时候,才知道栈顶元素在数组中右面第一个比栈顶元素大的元素是i
题目
LeetCode:739.每日温度
解法
将下标存放进单调栈中
当前遍历的元素和栈顶元素进行比较T[i]和T[st.pop()]
T[i]==T[st.pop()] 入栈
T[i]>T[st.pop()] 记录结果
T[i]<T[st.pop()] 入栈
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
stack<int> st;
vector<int> reulst(temperatures.size(),0);
st.push(0);//放入第一个元素
for(int i=1;i<temperatures.size();i++){
if(temperatures[i]<temperatures[st.top()]) st.push(i);
else if(temperatures[i]==temperatures[st.top()]) st.push(i);
else{
while(!st.empty()&&temperatures[i]>temperatures[st.top()]){
reulst[st.top()]=i-st.top();
st.pop();
}
st.push(i);
}
}
return reulst;
}
};
LeetCode:496.下一个更大
解法
class Solution {
public:
vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
vector<int> result(nums1.size(),-1); //结果数组的长度与1相等
stack<int> st;
if(nums1.size()==0) return result;
unordered_map<int,int> umap;
//对数组1进行处理 建立哈希表
for(int i=0;i<nums1.size();i++){
umap[nums1[i]]=i;
}
//用单调栈遍历数组2
st.push(0);
for(int i=1;i<nums2.size();i++){
if(nums2[i]<nums2[st.top()])//小于 等于 都直接入栈
st.push(i);
else if(nums2[i]==nums2[st.top()])
st.push(i);
else{
//大于栈顶元素 处理结果
while(!st.empty()&&nums2[i]>nums2[st.top()]){
//判断元素是否出现过
if(umap.count(nums2[st.top()])>0){
int index=umap[nums2[st.top()]];
result[index]=nums2[i];
}
st.pop();
}
st.push(i);
}
}
return result;
}
};
LeetCode:503.下一个更大元素II
用取模的过程模拟成环的遍历
for(i=0;i<nums.size()*2;i++){
i%nums.size()
}
class Solution {
public:
vector<int> nextGreaterElements(vector<int>& nums) {
vector<int> result(nums.size(),-1);
stack<int> st;
st.push(0);//放入第一个元素
for(int i=1;i<nums.size()*2;i++){
if(nums[i%nums.size()]<=nums[st.top()]) st.push(i%nums.size());
else{
while(!st.empty()&&nums[i%nums.size()]>nums[st.top()]){
result[st.top()]=nums[i%nums.size()];
st.pop();
}
st.push(i%nums.size());
}
}
return result;
}
};
LeetCode:42.接雨水
class Solution {
public:
int trap(vector<int>& height) {
stack<int> st;
st.push(0);
int sum=0;
//从1开始遍历所有柱子
for(int i=1;i<height.size();i++){
//如果当前遍历的元素(柱子)高度小于栈顶元素的高度,就把这个元素加入栈中,因为栈里本来就要保持从小到大的顺序(从栈头到栈底)
if(height[i]<height[st.top()]){
st.push(i);
}
//如果当前遍历的元素(柱子)高度等于栈顶元素的高度,要跟更新栈顶元素,因为遇到相相同高度的柱子,需要使用最右边的柱子来计算宽度。
else if(height[i]==height[st.top()]){
st.pop();
st.push(i);
}
//如果当前遍历的元素(柱子)高度大于栈顶元素的高度,此时就出现凹槽了
else{
while(!st.empty()&&height[i]>height[st.top()]){
int mid=height[st.top()];
st.pop();
if(!st.empty()){
int h=min(height[i],height[st.top()])-mid;
int w=i-st.top()-1;
sum+=h*w;
}
}
st.push(i);
}
}
return sum;
}
};
LeetCode:84.柱状图中最大的矩形
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int result=0;
stack<int> st;
heights.insert(heights.begin(), 0); // 数组头部加入元素0
heights.push_back(0); // 数组尾部加入元素0
st.push(0);
for(int i=1;i<heights.size();i++){//循环
//条件1 大于等于的情况
if(heights[i]>=heights[st.top()]){
st.push(i);
}
//条件2 小于的情况
else{
while(!st.empty()&&heights[i]<heights[st.top()]){
int mid=st.top();
st.pop();
if(!st.empty()){
int left=st.top();
int right=i;
int h=heights[mid];
int w=right-left-1;
result=max(result,w*h);
}
}
st.push(i);
}
}
return result;
}
};
感觉是最难理解的一部分了&完结撒花