力扣 739. 每日温度 & 496.下一个更大元素 I

  •  739. 每日温度

穷举的话就是从当前元素往后找比自己大的第一个元素,时间复杂度O(n^2)。

然后在看单调栈的解法。 就能感受出单调栈的巧妙。这道题主要熟悉单调栈这个数据结构。

单调栈:分为单调递增栈和单调递减栈。单调递增:栈顶元素总是小于(或等于)栈中所有其他元素。有时候根据题意,可能只有小于。

单调栈应用场景:一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时我们就要想到可以用单调栈了。时间复杂度为O(n)。

主要要模拟弄清这个过程,那么程序就好写了。

这里需要使用单调递增栈。

  • 当前遍历的元素T[i]小于栈顶元素T[st.top()]的情况
  • 当前遍历的元素T[i]等于栈顶元素T[st.top()]的情况
  • 当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况

搞清楚上面3种情况的操作:

(1)T[i]>T[st.top()]:目前是单调递增栈,都遵循这3个操作的话,i是top元素右边比自己大的第一个元素,所以可以得到result[st.top()]。现在得让i入栈,要满足这个栈仍然是单增栈,所以top出栈之后,还要接着比较栈顶和i,如果i还是>top的话,还得pop,并得到得到result[st.top()]……一直到栈顶元素比i大,既满足了单增栈(pop(),push()),又得到了栈头开始连续的这些比i小的元素的result值。

(2)T[i]<T[st.top()]:不是栈顶的result位置,直接入栈。

(3)T[i]==T[st.top()]:同样不是栈顶的result位置,入栈。

模拟一下过程更直观:

最后没有元素了,栈里面还剩一些元素,这些元素后面没有比他们大的了,所以按照题意直接是0,所以一开始都初始化为0.

代码如下。while是T【i】>T【top】的情况,因为情况1出栈、得到result之后就入栈,情况2和3直接入栈,所以s.push(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);
//简化后:
class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
           int n=temperatures.size();
           vector<int> result(n,0);
           stack<int> s;
           s.push(0);
           for(int i=1;i<n;++i){
                int top=s.top();
                while(temperatures[i]>temperatures[top]){   //一直大于栈顶,出栈
                    result[top]=i-top;
                    s.pop();
                    if(s.empty())break;
                    top=s.top();
                }
                s.push(i);  //入栈
           }
           return result;
    }
};
  •  496.下一个更大元素 I 

设置单调栈,同样是递增的,而后遍历nums2,根据上面的逻辑来进行出栈入栈,同时检查当前元素i在nums1中的下标j,然后更新result[j],j不存在不操作。检查i是否存在于nums1以及其下标很适合用map,即保存nums1各元素和下标的映射。

因为如果不存在下一个更大元素,那么本次查询的答案是 -1 。所以一开始都更新为-1,没有找到下一个更大元素的时候不会更新,保持为-1.

代码如下:

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        int n1=nums1.size();
        int n2=nums2.size();
        vector<int> result(n1,-1);
        map<int,int> nums1Map;
        for(int i=0;i<n1;++i)nums1Map.insert(pair<int,int>(nums1[i],i));
        stack<int> s;
        for(int i=0;i<n2;++i){
            while(!s.empty() && nums2[i]>nums2[s.top()]){
                map<int,int>::iterator it=nums1Map.find(nums2[s.top()]);
                if(it!=nums1Map.end())result[it->second]=nums2[i];
                s.pop();
            }
            s.push(i);
        }
        return result;
    }
};

上一篇:剑指offer面试题41 和为s的俩个数字 vs 和为s的连续正数序列-题目


下一篇:算法沉淀——贪心算法七(leetcode真题剖析)