LeetCode 503下一个更大元素II

LeetCode 503下一个更大元素IIMedium

  • 题目简述:给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。

  • 输入:[1,2,1] 输出:[2,-1,2] 解释:第一个 1 的下一个更大的数是 2;数字 2 找不到下一个更大的数;第二个 1 的下一个最大的数需要循环搜索,结果也是 2。

  • 思路:单调栈

    • 环形数组或是循环数组问题可以将该数组扩展两倍,即在原数组后再增加一组原数组,然后处理扩展数组;虽然需要扩展两倍数组,但是没有必要新建扩展数组,只需要通过下标取余数的方式操作原数组即可

      扩展数组 [1, 2, 1] [1, 2, 1]
      循环下标 0 1 2 3 4 5
      数组中下标 0 1 2 0 1 2
    • 依次遍历整个数组,先在空栈中压入第一个元素下标,然后用后面各个元素与当前栈顶元素比较,

      • 如果该元素比栈顶元素小,那么就将该元素下标加入栈中;
      • 如果该元素比栈顶元素大,那么就将栈顶元素弹出,然后用下一个栈顶元素比较,直到该元素小于栈顶或者栈为空,就将该元素加入栈中。保证了加入栈中的元素从栈底到栈顶依次递减
    • 每次栈中有元素弹出时,用数组记录每个弹出的栈顶元素下标对应的值,就是答案

class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        int n = nums.size();
        vector<int> res(n, -1);
        stack<int> st;
        for(int i = 0; i < 2 * n; i++)
        {
            while(!st.empty() && nums[i % n] > nums[st.top()])
            {
                res[st.top()] = nums[i % n];
                st.pop();
            }
            st.push(i % n);
        }
        return res;
    }
};
  • 思路二:从后往前依次遍历数组,找到比当前栈顶元素小的元素加入栈中,遇到比栈顶元素大的,就将栈顶元素弹出,直到小了为止或者栈空为止;每次栈中有元素弹出时用数组记录对应下标位置所求答案
class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        int n = nums.size();
        vector<int> res(n);
        stack<int> st;
        for(int i = 2 * n - 1; i >= 0; i--)
        {
            while(!st.empty() && nums[i % n] >= st.top()) st.pop();
            res[i % n] = st.empty() ? -1 : st.top();
            st.push(nums[i % n]);
        }
        return res;
    }
};

你可能感兴趣的:(LeetCode)