leetcode 503题

Posted by franki on November 3, 2022

leetcode 503 下一个更大元素 II

给定一个循环数组 nums ( nums[nums.length - 1] 的下一个元素是 nums[0] ),返回 nums 中每个元素的 下一个更大元素 。

数字 x 的 下一个更大的元素 是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1 。

示例1

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

示例2

输入: nums = [1,2,3,4,3]
输出: [2,3,4,-1,4]

思路

思路一:

利用循环数组的思想,首先遍历最外层数组,这个数组代表中,输入的每一个值,第二层循环用来判断下一个值是否比上一个值大,核心地方是 j !== i,这个时候就可以判断是否大于,当 j === i,则退出内层循环,这样做,可以保证,每个元素都最多找外层数组的长度的次数,如果找到比其大的,则放入结果中,如果内层循环走完了,还没找到,那么结果就放入 -1,遍历结束后,res 就是所求。

思路二:

利用栈先进后出的特点,形成一个单调递减栈,栈里面栈的元素始终是逐级递减的,特点是,当遇到下一个元素将要进栈的时候,先判断是否栈顶的元素,如果大于,那么当前栈顶元素被弹出(记得这里是循环,保证前面不存在比其小的元素);否则,就直接入栈;利用这个特点,我们可以找出下一个更大的元素;(被弹出的元素比其大的元素正是要即将进栈的元素),使用循环进行上述过程,即可得到答案。

代码

/**
 * @param {number[]} nums
 * @return {number[]}
 */
function nextGreaterElements(nums) {
    if (nums.length === 0) {
        return [];
    }

    const res = [];

    for (let i = 0; i < nums.length; i++) {
        let j = (i + 1) % nums.length;
        let find = false;
        while (j !== i) {
            if (nums[j] > nums[i]) {
                find = true;
                res.push(nums[j]);
                break;
            }
            j = (j + 1) % nums.length;
        }

        if (!find) {
            res.push(-1);
        }
    }

    return res;
}

// 单调栈实现
function nextGreaterElements(nums) {
    const length = nums.length;
    const res = new Array(length).fill(-1);
    const stack = []; // 存放的是数组元素的下标,方便找到元素

    for (let i = 0; i < 2 * length; i++>) {
        const num = nums[i % length];
        while (stack.length && num > nums[stack[stack.length - 1]]) {
            const topIndex = stack.pop();
            res[topIndex] = num;
        }

        stack.push(i % length);
    }

    return res;
}

复杂度分析:

  • 时间复杂度: O(N^2)
  • 空间复杂度:O(N)