前言
打卡断了几天,今天开始写单调栈。
单调栈顾名思义就是用一个栈保存元素,里面的元素大小是单调的,要么从小到大,要么从大到小。利用单调栈可以轻松找到一个元素两边离他最近的最大或最小元素,具体操作直接看题目。
739. 每日温度
思路
题目要求查找某天温度之后是否还有出现比它大的温度值,有则返回它与当天的相隔天数。这就可以利用单调栈,栈内元素按照从栈头到栈底从小到大的顺序。
当栈内元素为空,把当前元素push进栈,再依次向后遍历,和栈顶元素比较。
比较会产生三种结果:
- 当前遍历的元素T[i]小于栈顶元素T[st.top()]的情况
- 当前遍历的元素T[i]等于栈顶元素T[st.top()]的情况
- 当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况
情况一:还没遍历到比它温度高的最近元素T[i],先保存当前温度
情况二:和情况一一样进栈
情况三:找到了栈顶元素之后的天数中比它大的最近元素T[i],他们两相隔天数就是i - st.top(),不过记得把栈顶元素pop出栈
代码实现
这里我先自己用了个pari元素分别保存坐标和温度,然后发现直接保存下标就好了,会更方便也不浪费内存。
- 用pair
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
stack<pair<int,int>> st;
vector<int> result(temperatures.size(),0);
pair<int,int> tmp(0,temperatures[0]);
st.push(tmp);
for(int i=1;i<temperatures.size();i++){
pair<int,int> tmp(i,temperatures[i]);
while(!st.empty()&&temperatures[i]>st.top().second){
result[st.top().first]=i-st.top().first;
st.pop();
}
st.push(tmp);
}
return result;
}
};
- 直接保存下标
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;
}
};
496.下一个更大元素 I
思路
题目要求是从num2序列中找到num1的各个元素在num2中下一个最大元素的多少。
- 暴力搜寻法
求num2的下一个最大元素也是用单调栈就可以解决。
再用两个for循环遍历num1,和num2,就可以得到最大元素位置。这个方法时间复杂度稍微高一点,但是便于理解。 - 直接查找法
用unordered_map来保存num1的元素,在用单调栈计算num2的下一个最大元素的同时,直接用if (umap.count(nums2[st.top()]) > 0)来判断num1内是否有st.top(这个元素),没有就直接pop出去,反正不需要记录结果。
代码实现
- 暴力搜寻法
class Solution {
public:
vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
stack<int> st;
vector<int> tmp(nums2.size(),-1);
vector<int> result(nums1.size());
st.push(0);
for(int i=1;i<nums2.size();i++){
while(!st.empty()&&nums2[i]>nums2[st.top()]){
tmp[st.top()]=nums2[i];
st.pop();
}
st.push(i);
}
for(int i=0;i<nums1.size();i++){
for(int j=0;j<nums2.size();j++){
if(nums1[i]==nums2[j]){
result[i]=tmp[j];
}
}
}
return result;
}
};
- 直接查找法
class Solution {
public:
vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
stack<int> st;
vector<int> result(nums1.size(), -1);
if (nums1.size() == 0) return result;
unordered_map<int, int> umap; // key:下标元素,value:下标
for (int i = 0; i < nums1.size(); i++) {
umap[nums1[i]] = i;
}
st.push(0);
for (int i = 1; i < nums2.size(); i++) {
while (!st.empty() && nums2[i] > nums2[st.top()]) {
if (umap.count(nums2[st.top()]) > 0) { // 看map里是否存在这个元素
int index = umap[nums2[st.top()]]; // 根据map找到nums2[st.top()] 在 nums1中的下标
result[index] = nums2[i];
}
st.pop();
}
st.push(i);
}
return result;
}
};