题目描述
给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/next-greater-element-ii
示例1:
输入: [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数;
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。
注意:
- 输入数组的长度不会超过 10000。
解题思路
关键词:
- 循环数组
- 单调栈
思路:
- 简单的暴力求解可以通过,但太low了。
- 循环数组:脚标取模。每个元素最多读取两次。
循环体内的 i 均写成 i % n
。 - 结果数组(res):初值均为 -1。
- 单调栈(stk):判断痕迹,记录大值。
筛选条件:
- 栈空,直接入栈
- 新项a 小于栈顶b ,a入栈,成为新栈顶
- 新项a 大于栈顶B ,B出栈, a入栈,成为新的栈顶。修改出栈的对应res值为 a。(B 是所有小于a 的集合)
我的代码
class Solution:
def nextGreaterElements(self, nums: List[int]) -> List[int]:
n = len(nums)
res = [-1] * n # 构建结果数组
stk = [] # 构建单调栈
for i in range(n * 2 - 1): # 每个元素最多读取两次
while stk and nums[stk[-1]] < nums[i % n]: # 取模判断新项与旧项的大小,新项大于旧项时,不断出栈
res[stk.pop()] = nums[i % n]
stk.append(i % n) # stk 内记录脚标,便于res更改值
return res
时间复杂度: O(n)。
空间复杂度: O(n)。
心得
- 单调栈记录脚标,配合筛选条件进行挑选。
- 刷题尽量减少
暴力求解
的思路。