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)