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

    总结

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

  • 相关阅读:
    单元测试的必要性
    【C++ STL】Queue
    【C++ STL】Stack
    【C++ STL】容器的选择
    【C++ STL】Map和Multimap
    [Effective JavaScript 笔记]第19条:熟练掌握高阶函数
    [Effective JavaScript 笔记]第18条:理解函数调用、方法调用及构造函数调用之间的不同
    node实现rar格式压缩
    [Effective JavaScript 笔记]第2章:变量作用域--个人总结
    [Effective JavaScript 笔记]第17条:间接调用eval函数优于直接调用
  • 原文地址:https://www.cnblogs.com/flix/p/12917383.html
Copyright © 2020-2023  润新知