文章链接: 739. 每日温度 496.下一个更大元素 I 503.下一个更大元素II

视频链接: 739. 每日温度 496.下一个更大元素 I 503.下一个更大元素II

题目链接: 739. 每日温度 496.下一个更大元素 I 503.下一个更大元素II


739.每日温度

思路:

:为什么会想到用单调栈?什么时候用单调栈?

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

单调栈里存放的元素是什么?

:下标,便于计算距离。

:什么时候用递增,什么时候用递减?(从栈头到栈底的顺序

:如果求一个元素右边第一个更大元素,单调栈就是递增的,如果求一个元素右边第一个更小元素,单调栈就是递减的。

:使用单调栈主要有三个判断条件。

:(从这三个判断条件出发,更好的理解单调栈。)

1.当前遍历的元素T[i]小于栈顶元素T[st.top()]的情况:直接将遍历的元素下标加入单调栈中;

2.当前遍历的元素T[i]等于栈顶元素T[st.top()]的情况:直接将遍历的元素下标加入单调栈中;

3.当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况:将栈顶元素弹出,遍历的元素放入栈中;并用result数组记录,result[0] = 1(遍历的元素下标 - 栈顶),即T[0]右面第一个比T[0]大的元素是T[1]。(注意是一直弹出,直至遍历的元素小于等于栈顶元素


class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        stack<int> st;
        vector<int> result(temperatures.size(), 0);
        st.push(0);
        for (int i = 0; i < temperatures.size(); i++) {
            if (temperatures[i] <= temperatures[st.top()]) { // 情况一和二
                st.push(i);
            } else {
                while (!st.empty() && temperatures[i] > temperatures[st.top()]) { // 情况三
                // 注意是要一直弹出
                    result[st.top()] = i - st.top();
                    st.pop();
                }
                st.push(i);
            }

        }
        return result;
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.


496.下一个更大元素 I

思路:

与上一题的区别就是:需要用map做一个哈希映射以判断遍历到的元素是否出现在nums1中,若出现,才将需要的结果(即nums2[j] 的下一个更大元素 )放入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);// 下标 0
        for (int i = 1; i < nums2.size(); i++) {
            if (nums2[i] < nums2[st.top()]) {  
                st.push(i);
            } else {
                while (!st.empty() && nums2[i] > nums2[st.top()]) {
                    if (umap.count(nums2[st.top()]) > 0) { // 判断是否是nums1中的元素
                        int index = umap[nums2[st.top()]]; // 找元素对应的nums1中的下标
                        result[index] = nums2[i]; // 放入nums2[j] 的下一个更大元素
                    }
                    st.pop();
                }
                st.push(i);
            }
        }   
        return result; 
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.


503.下一个更大元素II

思路:

本题的关键是如何处理循环数组

思路一:将两个nums数组拼接在一起,使用单调栈计算出每一个元素的下一个最大值,最后再把结果集即result数组resize到原数组大小就可以了。

思路二:(重要!!!重要!!!重要!!!

可以不扩充nums,而是在遍历的过程中用 i % nums.size()来模拟走了两遍nums。

// 思路一
class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        vector<int> nums1(nums.begin(), nums.end()); // 复制nums数组
        nums.insert(nums.end(), nums1.begin(), nums1.end()); // 将两个nums数组拼接在一起

        vector<int> result(nums.size(), -1);
        if (nums.size() == 0) return result;

        stack<int> st;
        st.push(0); // 下标
        for (int i = 1; i < nums.size(); i++) {
            if (nums[i] <= nums[st.top()]) {
                st.push(i);
            } else {
                while (!st.empty() && nums[i] > nums[st.top()]) {
                    result[st.top()] = nums[i];
                    st.pop();
                }
                st.push(i);
            }
        }
        result.resize(nums.size() / 2); // 最后再把结果集即result数组resize到原数组大小
        return result;
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.


// 思路二
class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        vector<int> result(nums.size(), -1);
        if (nums.size() == 0) return result;

        stack<int> st;
        st.push(0); // 下标
        for (int i = 1; i < nums.size() * 2; i++) {
            if (nums[i % nums.size()] <= nums[st.top()]) {
                st.push(i % nums.size());
            } else {
                while (!st.empty() && nums[i % nums.size()] > nums[st.top()]) {
                    result[st.top()] = nums[i % nums.size()];
                    st.pop();
                }
                st.push(i % nums.size());
            }
        }
        return result;
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.