这是我碰到的一道非常经典的单调栈的题目,题目中考察的正是单调栈的特性及用法,可以一起学习一下。
题目描述
给定一个循环数组 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 <= nums.length <= 10(4)
-10(9) <= nums[i] <= 10(9)
解析 1
何为单调栈,即栈中栈底到栈顶存储的数字是单调的,而在本题中栈中存放的数组中对应的下标,这些下标所对应的数组中的数字在栈中是单调不升的。
总体思路为:
- 因为数组为循环数组,所以要遍历两边数组
- 如果栈不为空且栈顶元素小于等于当前元素,将弹出栈顶元素,并将弹出元素的下个最大元素设为当前元素
- 并将当前元素下标压栈
- 重复以上过程
遍历数组时,当前元素为 nums[i]
,当前栈顶元素值小于该数组元素时,栈顶元素的下个更大值即为当前元素 nums[i]
。只要遍历到比栈顶元素值更大的数,就意味着栈顶元素找到了答案,记录答案,然后弹出栈顶。
参考
1 | public int[] nextGreaterElements(int[] nums) { |
时间复杂度:
O(n)
空间复杂度:
O(n)
解析 2
解析 1 中是从左至右遍历数组中的元素的,还有一种自右向左遍历的思路,总体算法思路相似,细节略有不同。
自右向左遍历,栈中记录的是下一个更大元素的 次选
。
参考 2
1 | public int[] nextGreaterElements(int[] nums) { |
时间复杂度:
O(n)
空间复杂度:
O(n)