单调栈
通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时我们就要想到可以用单调栈了。
单调栈的用处
单调栈中存储的值
单调栈中存储的是已经遍历过的数据
然后栈顶元素和当前数据做比较,就可以求出对应逻辑的值
个人观点
- 单调栈,在画图的的时候,把栈口方向朝向右边,会更好理解。
- 栈中的元素就是遍历过的,没有处理过的元素。
- 因为都是在找和栈口元素有大小关系,当前遍历的元素还没处理,所以当前遍历到的元素是一定是要入栈的
- 找到符合条件的就处理栈口的元素,所以不需要判断栈中是递增还是递减,直接处理就好
- 判断栈是单调递增还是单调递减
就看要求的是比栈顶元素大还是小,求得是比栈顶元素大的就是单调递增的,求得是比栈顶元素小的就是递减的( 大就是递增,小就是递减)
739. 每日温度
大家可以读题,思考暴力的解法,然后在看单调栈的解法。 就能感受出单调栈的巧妙
单调栈中存放的是数据的下标
每次取数组的数据和栈顶元素做比较,如果当前元素比栈顶元素大,就将结果存储
所以栈中的元素从栈顶到栈底是递增的
核心
获取比栈顶元素大的第一个元素
// 版本一
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& T) {
// 递增栈
stack<int> st;
vector<int> result(T.size(), 0);
st.push(0);
for (int i = 1; i < T.size(); i++) {
if (T[i] < T[st.top()]) { // 情况一
st.push(i);
} else if (T[i] == T[st.top()]) { // 情况二
st.push(i);
} else {
while (!st.empty() && T[i] > T[st.top()]) { // 情况三
result[st.top()] = i - st.top();
st.pop();
}
st.push(i);
}
}
return result;
}
};
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
stack<int> st;// stack 存储的是数据的下标
vector<int> result(temperatures.size(), 0);
for(int i = 0; i < temperatures.size(); i ++){
//如果当前节点比栈顶元素大,说明当前元素是第一个比栈顶元素大的值,
//需要继续判断栈顶元素,直到当前节点比元素小或者相等
while(!st.empty() && temperatures[i] > temperatures[st.top()]) {
result[st.top()] = i - st.top();
st.pop();
}
//stack 存储的是数据的下标
// 不管如何也要把 当前节点加入进来,因为比当前节点大的值还没找出来
st.push(i);
}
return result;
}
};
496.下一个更大元素 I
题目描述:
给你两个 没有重复元素 的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。
请你找出 nums1 中每个元素在 nums2 中的下一个比其大的值。
题目分析:
此题是在获取下一个大的元素,获取的元素是在nums1中存在的时候 的下一个元素
就是如果栈顶元素是nums1 中的元素,那么就获取结果,如果不是就继续获取下一个元素的代码
class Solution {
public:
vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
vector<int> result(nums1.size(), -1);
unordered_map<int,int> nmap;
stack<int> stack;
//将nums1 的数据映射到map中,key为nums中的值,value是下标
for(int i = 0; i < nums1.size(); i ++) {
nmap[nums1[i]] = i;
}
for(int i = 0; i < nums2.size(); i ++) {
while(!stack.empty() && nums2[i] > nums2[stack.top()]) {
//如果栈顶的元素在nums2存在,就获取结果
//每次都是在给栈顶元素的下一个值做处理,给栈顶的元素对应的结果赋值
if(nmap.count(nums2[stack.top()]) > 0) {
//先通过nums2的值找到当前的栈顶的元素的实际值 ,再通过实际值和nmap找到对应到nums1中的下标
int nums1_index = nmap[nums2[stack.top()]];
result[nums1_index] = nums2[i];
}
stack.pop();
}
stack.push(i);
}
return result;
}
};