【LeetCode】503, 下一个更大元素 II。 难度等级:中等。深入理解 “下一个更大/更小问题” 常用的单调栈方法

0. 题目

给定一个循环数组 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]

1. 我的解法:单调栈

1.1 分析

本题与 【LeetCode】739, 每日温度。 难度等级:中等。多种解法,值得研究 非常相似,建议先看 739题

本题比 739 题更难的两个点是:

  1. 数组要首尾循环,因此要想办法实现数组循环遍历。
  2. 如果某个数不存在更大的数,则返回-1;其实就是要额外找到数组中的所有最大值的位置(最大值不止一个)

这两个难点都有巧妙的解决办法:

  1. 直接循环遍历数组很麻烦,换个思路,将数组复制一下,拼成一个是原来2倍长度的新数组,遍历一次新数组不就相当于循环遍历了两次原数组吗?
  2. 将返回值列表用 -1 初始化,有更大值的位置会用新值覆盖,最大值的位置就不会做处理,仍然会保留 -1

这样两个难点都解决了,我们接下来考虑用什么方法。结论是:

对于「找最近一个比当前值大/小」的问题,都可以使用单调栈来解决

为什么这种问题都能用单调栈呢?详细解释可以参考 为啥使用「单调栈」呀?从「朴素解法」的角度去理解「单调栈」

1.2 初级代码,根据单调栈思路直接写

根据单调栈思路直接写出来的代码如下:

class Solution:
    def nextGreaterElements(self, nums: List[int]) -> List[int]:
        # 实现循环的一种方法:将数组复制一遍;取前 nums 个结果即可
        new_nums=nums*2
        length=len(new_nums)
        ans=[-1]*length    # 为了避免单独判断最大的元素的位置,用-1初始化数组

        stack=[]
        for i in range(length):
            if not stack:
                stack.append([i,new_nums[i]])
            else:
                if new_nums[i]>stack[-1][1]:
                    while stack and new_nums[i]>stack[-1][1]:
                        ans[stack[-1][0]]=new_nums[i]
                        stack.pop()
                    stack.append([i,new_nums[i]])
                else:
                    stack.append([i,new_nums[i]])
        return ans[:length//2]

1.3 简化版代码

很显然,1.2 中的代码实可以简化的,简化后的代码如下:

class Solution:
    def nextGreaterElements(self, nums: List[int]) -> List[int]:
        # 实现循环的一种方法:将数组复制一遍;取前 nums 个结果即可
        new_nums=nums*2
        length=len(new_nums)
        ans=[-1]*length    # 为了避免单独判断最大的元素的位置,用-1初始化数组

        stack=[]
        for i in range(length):
            if not stack:
                stack.append([i,new_nums[i]])
            else:
                while stack and new_nums[i]>stack[-1][1]:
                    ans[stack[-1][0]]=new_nums[i]
                    stack.pop()
                stack.append([i,new_nums[i]])
        return ans[:length//2]

猜你喜欢

转载自blog.csdn.net/qq_43799400/article/details/131730916