[LeetCode503. 下一个更大元素 II]|刷题打卡

205 阅读2分钟

题目描述

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

示例 1:


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

难度:中等

注意: 输入数组的长度不会超过 10000。

思路分析

解题流程

  1. 分析描述及结合示例:找到比目标元素大的下一个元素。

    // 当前元素
    let target = nums[i]
    
  2. 给定是一个循环数组 , 按顺序在目标值后的元素和目标值前的元素中查找。

  3. 数据slice方法截取前、后的元素合并后,在其中查找

    // 待查找数据
    let detectNums = nums.slice(i+1).concat(nums.slice(0,i))
    
  4. 找到比目标值得元素,则加入结果值中result中,没有则添加-1 到result中。

  5. 循环结束后返回result.

单调栈优化解题流程:

  1. 循环数组,通过复制数组,取值时i%len去到对应的值。

  2. 栈中记录每个入栈的元素的下标。

  3. 若栈不为空, 则每次取栈尾元素nums[stack[stack.length - 1]]和目标元素做nums[i%len]对比,

  4. 如果栈尾元素小于目标元素,则说明栈尾下标指向的元素的下一个最大元素找到了为target,将result[stack[stack.length - 1]] = target 更新。

AC代码

  1. 简单思路实现的逻辑代码,通过了但是耗时、内存占用都比较大(暴力破解法)

    /**
     * @param {number[]} nums
     * @return {number[]}
     */
    var nextGreaterElements = function(nums) {
        let result = []
        let len = nums.length;
        let i = 0;
        while(i<len){
            // 被检测元素
            let target = nums[i]
            // 检测数据
            let detectNums = nums.slice(i+1).concat(nums.slice(0,i))
            // 排序找出最大元素 , 然后去最大元素
            // detectNums.sort()
            // 目标结果值
            // let targetResult = detectNums[detectNums.length - 1]
            // 下一最大值, 不是最大值
            let targetResult = detectNums.find(val=>val>target)
            // targetResult>target?result.push(targetResult):result.push(-1)
            targetResult!==undefined?result.push(targetResult):result.push(-1)   
            i++
        }
        return result
    };
    
  2. 根据题目题目的标签提示单调栈来优化代码,参考官方题解,理解解题思想。

    /**
     * @param {number[]} nums
     * @return {number[]}
     */
    var nextGreaterElements = function(nums) {
        let len = nums.length
        // 结果值 默认都为 -1 ,待找到下一个更大值时替换
        let result = new Array(len).fill(-1)
        // 栈
        let stack = []
        for(let i=0;i<len*2;i++){
            let target = nums[i%len]
            while(stack.length>0 && target>nums[stack[stack.length - 1]]){
                result[stack[stack.length - 1]] = target
                stack.pop()
            }
            if(i<len) stack.push(i)
        }
        return result
    };
    

总结

  1. 第一次提交失败,没有考虑到find函数查找不到的时候返回undefined . 导致在用例中有负数以及0 时,结果值targetResult为 0时,三元表达值判定失败。

  2. 数组方法的使用slice(start,end) 不包含end位置上的数据;find函数找不到数据时返回undefined.

  3. 单调栈 解题思想的理解。