单调栈
三步走:(这个三步走一开始有点难理解,可以刷了几道题回来再理解)
- 维护一个单调栈
- 处理结果
- 插入栈
496. 下一个更大元素 I
class Solution {
public:
vector<int> nextGreaterElement(vector<int>& v1, vector<int>& v2) {
// 单调栈 + map
map<int,int> m;
stack<int> s;
vector<int> ans;
for(int i = v2.size() - 1 ; i >= 0; --i){
// 1. 维护单调栈, 这里是栈顶最小
int n = v2[i];
while( s.size() && n >= s.top() ) s.pop();
// 2. 处理结果
m[n] = s.empty() ? -1 : s.top();
// 3. 插入栈
s.push(n);
}
// map
for(int val : v1){
ans.push_back(m[val]);
}
return ans;
}
};
503. 下一个更大元素 II
class Solution {
public:
vector<int> nextGreaterElements(vector<int>& v) {
// 单调栈, 这里是栈顶最小
int n = v.size();
stack<int> s;
vector<int> ans(n,-1);
for(int i = 2*n -1; i>=0 ;--i){
// 1.维护单调栈
while(s.size() && v[i%n] >= s.top()) s.pop();
// 2.处理结果
ans[i%n] = s.empty() ? -1 : s.top();
// 3.插入栈
s.push(v[i%n]);
}
return ans;
}
};
1019. 链表中的下一个更大节点
class Solution {
public:
vector<int> nextLargerNodes(ListNode* head) {
// 单调栈
vector<int> v;
stack<int> s;
// 转换成vector
while(head) v.push_back(head->val),head=head->next;
int n = v.size();
vector<int> ans(n,0);
for(int i = n-1; i>= 0; --i){
// 1. 维护单调栈, 这里是栈顶最小
while( s.size() && v[i] >= s.top()) s.pop();
// 2. 处理结果
ans[i] = s.empty() ? 0 : s.top();
// 3. 插入栈
s.push(v[i]);
}
return ans;
}
};
难度升级,开始变种:
739. 每日温度
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& v) {
// 单调栈 , 栈顶是最小温度对应的index
int n = v.size();
stack<int> s;
vector<int> ans(n,0);
for(int i = n-1;i>=0;--i){
int cur = v[i];
// 1.维护栈
while(s.size() && cur >= v[s.top()]) s.pop();
// 2.处理结果
ans[i] = s.empty() ? 0 : s.top() - i;
// 3.插入栈
s.push(i);
}
return ans;
}
};
难度升级
1081. 不同字符的最小子序列
class Solution {
public:
string smallestSubsequence(string s) {
// 单调栈,栈顶元素更大
stack<char> st;
unordered_map<char,int> cnt;
unordered_map<char,int> inst;
for(auto& val : s) ++cnt[val];
for(int i=0;i<s.size();i++){
char c = s[i];
if(inst[c]){
--cnt[c];
continue;
}
// 1. 维护栈
while(!st.empty() && c<st.top() && cnt[st.top()]>0){
inst[st.top()] = false;
st.pop();
}
// 3. 入栈
st.push(c);
inst[c] = true;
--cnt[c];
}
// 2. 处理结果
string ans;
while(!st.empty()){
ans = st.top() + ans;
st.pop();
}
return ans;
}
};
402. 移掉 K 位数字
class Solution {
public:
string removeKdigits(string num, int k) {
stack<char> s;
// 单调栈
for(auto& val : num){
// 1. 维护单调栈
while(s.size() && k>0 && val<s.top()){
s.pop();
k--;
}
// 3. 入栈
s.push(val);
}
while(k){
s.pop();
k--;
}
// 2. 处理结果 去掉前缀"0",方法有点憨憨
string ans ;
stack<char> tmp;
while(!s.empty()){
tmp.push(s.top());
s.pop();
}
while(!tmp.empty() && tmp.top()=='0'){
tmp.pop();
}
while(!tmp.empty()){
ans = ans + tmp.top();
tmp.pop();
}
return ans.empty() ? "0" : ans;
}
};
其他单调栈: