【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;
    }
};

总结

单调栈问题的明显特征为:求一个数之后第一个更大或者更小的数。

posted @ 2020-05-19 15:50  Flix  阅读(156)  评论(0编辑  收藏  举报