文章目录
- 0. 题目
- 1. 我的解法:单调栈
- 1.1 分析
- 1.2 初级代码,根据单调栈思路直接写
- 1.3 简化版代码
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
这样两个难点都解决了,我们接下来考虑用什么方法。结论是:
对于「找最近一个比当前值大/小」的问题,都可以使用单调栈来解决
为什么这种问题都能用单调栈呢?详细解释可以参考 为啥使用「单调栈」呀?从「朴素解法」的角度去理解「单调栈」
1.2 初级代码,根据单调栈思路直接写
根据单调栈思路直接写出来的代码如下:
class Solution:def nextGreaterElements(self, nums: List[int]) -> List[int]:# 实现循环的一种方法:将数组复制一遍;取前 nums 个结果即可new_nums=nums*2length=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*2length=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]