【LeetCode-栈】每日温度
题目描述
根据每日 气温 列表,请重新生成一个列表,对应位置的输出是需要再等待多久温度才会升高超过该日的天数。如果之后都不会升高,请在该位置用 0 来代替。
例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。
提示: 气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。
题目链接: https://leetcode-cn.com/problems/daily-temperatures/
思路1
首先理解题目的意思,73 的输出为 1 表示 73 之后第一天(天数从 1 开始)的温度超过了 73(74),75 是 4 的意思是 75 之后第 4 天的温度超过了 75(76),其他的依次类推。所以,我们可以使用
两层循环来做,代码如下:
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& T) {
if(T.empty()) return {};
vector<int> ans;
for(int i=0; i<T.size(); i++){
bool flag = false;
for(int j=i+1; j<T.size(); j++){
if(T[j]>T[i]){
ans.push_back(j-i);
flag = true;
break;
}
}
if(!flag) ans.push_back(0);
}
return ans;
}
};
// 超时
- 时间复杂度:O(n^2)
- 空间复杂度:O(n)
思路2
使用单调栈来做。如果一个题目要求当前数字的下一个更小或者更大的数字,那么通常要使用单调栈。
单调栈分为单调递增栈和单调递减栈。单调递增栈从栈底到栈顶的元素是递增的,单调递减栈则相反。这里我们使用的是单调递减栈。入栈方法如下:
- 如果当前元素小于栈顶元素,则直接入栈;
- 否则,则将栈中的元素弹出,直至当前元素小于栈顶元素,然后将当前元素入栈。在弹出的过程中,由于当前元素是第一个大于栈顶元素的值,所以两者的下标相减就是要求的答案。
代码如下:
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& T) {
if(T.empty()) return {};
stack<pair<int, int>> s;
s.push(make_pair(0, T[0]));
vector<int> ans(T.size(), 0);
for(int i=1; i<T.size(); i++){
if(T[i]>s.top().second){
while(!s.empty() && T[i]>s.top().second){
int idx = s.top().first;
int temp = s.top().second;
s.pop();
ans[idx] = i-idx;
}
s.push(make_pair(i, T[i]));
}else{
s.push(make_pair(i, T[i]));
}
}
return ans;
}
};
- 时间复杂度:O(n)
- 空间复杂度:O(n)
简化的写法:
下面的写法栈中只存储下标,写法更简洁也更快:
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& T) {
if(T.empty()) return {};
stack<int> s;
vector<int> ans(T.size(), 0);
for(int i=0; i<T.size(); i++){
while(!s.empty() && T[i]>T[s.top()]){
ans[s.top()] = i - s.top();
s.pop();
}
s.push(i);
}
return ans;
}
};
或者这样写,稍微麻烦一点,但更好理解:
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& T) {
if(T.empty()) return {};
vector<int> ans(T.size(), 0);
stack<int> s;
for(int i=0; i<T.size(); i++){
if(s.empty() || T[i]<=T[s.top()]) s.push(i);
else{
while(!s.empty() && T[i]>T[s.top()]){
int idx = s.top(); s.pop();
ans[idx] = i-idx;
}
s.push(i);
}
}
return ans;
}
};
或者这样写:
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& tp) {
stack<pair<int, int>> s;
vector<int> ans(tp.size(), 0);
for (int i = 0; i < tp.size(); i++) {
if (s.empty() || tp[i] <= s.top().second) {
s.push({i, tp[i]});
} else {
while (!s.empty() && tp[i] > s.top().second) {
auto [idx, t] = s.top(); s.pop();
ans[idx] = i - idx;
}
s.push({i, tp[i]});
}
}
return ans;
}
};
总结
单调栈问题的明显特征为:求一个数之后第一个更大或者更小的数。