最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 20210306 LeetCode 每日一题,冲!|刷题打卡

    正文概述 掘金(小诸不是小猪)   2021-03-06   497

    题目描述

    Leetcode 链接:503. 下一个更大元素 II(medium)

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

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

    提示:

    • 输入数组的长度不会超过 10000。

    JavaScript 模板:

    /**
     * @param {number[]} nums
     * @return {number[]}
     */
    var nextGreaterElements = function(nums) {
    
    };
    

    思路分析

    首先,我们可以对 nums 中每一个元素遍历一次 nums 数组,用于找出比它大的下一个值,这个方法比较直观,我们直接来看代码:

    时间复杂度为 O(n2),对每一个元素进行一次遍历 空间复杂度为 O(1),仅使用单一变量 found

    var nextGreaterElements = function (nums) {
      const result = [];
      for (let i = 0; i < nums.length; i++) {
        let found = false; // 标识是否已找到,若找到则停止遍历
        // 遍历 i 之后的元素
        for (let j = i + 1; j < nums.length && !found; j++) {
          if (nums[j] > nums[i]) {
            result.push(nums[j]);
            found = true;
          }
        }
        // 遍历 i 之前的元素
        for (let j = 0; j < i && !found; j++) {
          if (nums[j] > nums[i]) {
            result.push(nums[j]);
            found = true;
          }
        }
        !found && result.push(-1); // 若遍历完成都找不到则推入 -1
      }
      return result;
    };
    

    优化一下

    我们可以维护一个栈 stack 用于储存 nums 中元素的索引,并初始化返回数组 result,为其每一个元素赋值为 -1。

    首先,我们循环会检查当前 stack 顶部的索引所对应的值 nums[stack[stack.length -1]] 是否小于 nums[i],若小于,则说明顶部索引所对应的值的下一个最大值便是 nums[i],我们将 result 数组中的对应值修改即可,然后我们弹出 stack 顶部的值。

    其次,我们把当前的索引 i 推入 stack 即可。

    直接这样梳理逻辑可能并不是很容易理解,我们来看一个例子:

    假设 nums = [1, 3, 2, 5, 4] 其对应索引为 0, 1, 2, 3, 4

    istackresult解析
    0[0][-1, -1, -1, -1, -1]stack 中无元素,直接推入当前索引 i1[1][3, -1, -1, -1, -1]nums[i] 大于 nums[stack[stack.length -1]] ,我们将其对应的 result 中的值改为 nums[i] ,然后弹出 stack 顶部的元素,并插入当前索引 i2[1, 2][3, -1, -1, -1, -1]nums[i] 不大于 nums[stack[stack.length -1]],我们直接推入当前索引 i3[3][3, 5, 5, -1, -1]nums[i] 大于 nums[stack[stack.length -1]] ,我们将其对应的 result 中的值改为 nums[i] ,然后弹出 stack 顶部的元素;我们接着进行对比,发现下一个也符合,便对其进行同样的操作,然后再插入索引 i 。所以这一步中,我们从 stack 中弹出了两个元素的并修改了它们对应的 result4[3, 4][3, 5, 5, -1, -1]nums[i] 不大于 nums[stack[stack.length -1]],我们直接推入当前索引 i

    具体代码如下:

    var nextGreaterElements = function (nums) {
      const result = Array(nums.length).fill(-1), stack = [];
      for (let i = 0; i < nums.lengt; i++) {
        while (nums[stack[stack.length -1]] < nums[i]) {
          result[stack[stack.length -1]] = nums[i];
          stack.pop();
        }
        stack.push(i);
      }
      return result;
    };
    

    这样我们就得到了结果 [3, 5, 5, -1, -1]。但其实这并不是完全正确的,因为 nums 数组最后的元素 4 是可以发现比他大的元素 5 的(因为是循环数组),所以在遍历时,我们需要额外遍历一遍数组。我们可以将遍历的条件修改成 i < nums.length * 2 - 1,并且对将 i 改为 i % nums.length 来确保其不会超出上限:

    var nextGreaterElements = function (nums) {
      const result = Array(nums.length).fill(-1),
        stack = [];
      for (let i = 0; i < nums.length * 2 - 1; i++) {
        while (nums[stack[stack.length - 1]] < nums[i % nums.length]) {
          result[stack[stack.length - 1]] = nums[i % nums.length];
          stack.pop();
        }
        stack.push(i % nums.length);
      }
      return result;
    };
    

    这样我们就以更低的时间复杂度完成了该题:

    时间复杂度为 O(n),在循环中每一个元素最多出入栈 4 次,所以为 O(n)

    空间复杂度为 O(n),因为维护了一个数组 stack

    总结一下

    这道题的话可以使用暴力手法以时间复杂度为 O(n2)求出答案,不过也可以通过使用栈来减少时间复杂度来做出更优的解。

    • 小伙伴们一起来用 JavaScript 刷算法吧:LeetCode-JavaScript

    • 本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情


    起源地下载网 » 20210306 LeetCode 每日一题,冲!|刷题打卡

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元