单调栈
1. 下一个更大元素 I
1.1 题目描述
给你两个 没有重复元素 的数组
$nums1$
和$nums2$
,其中$nums1$
是$nums2$
的子集。
请你找出$nums1$
中每个元素在$nums2$
中的下一个比其大的值。
$nums1$
中数字$x$
的下一个更大元素是指$x$
在$nums2$
中对应位置的右边的第一个比$x$
大的元素。如果不存在,对应位置输出$-1$
。
输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
解释:
对于 num1 中的数字 4 ,你无法在第二个数组中找到下一个更大的数字,因此输出 -1 。
对于 num1 中的数字 1 ,第二个数组中数字1右边的下一个较大数字是 3 。
对于 num1 中的数字 2 ,第二个数组中没有下一个更大的数字,因此输出 -1 。
输入: nums1 = [2,4], nums2 = [1,2,3,4].
输出: [3,-1]
解释:
对于 num1 中的数字 2 ,第二个数组中的下一个较大数字是 3 。
对于 num1 中的数字 4 ,第二个数组中没有下一个更大的数字,因此输出 -1 。
1.2 解题思路 单调栈
单调栈实际上就是栈,只是利用了一些巧妙的逻辑,使得每次新元素入栈后,栈内的元素都保持有序(单调递增或单调递减)。单调栈用途不太广泛,只处理一种典型的问题,叫做
$ Next Greater Element$
。
func nextGreaterElement(nums1 []int, nums2 []int) []int {
res := make([]int, len(nums1))
stack := make([]int, 0)
mp := make(map[int]int)
// 单调栈
for _, num := range nums2 {
// 栈内元素小于新元素 栈内元素出栈
for len(stack)>0 && num > stack[len(stack)-1] {
mp[stack[len(stack)-1]] = num
stack = stack[:len(stack)-1]
}
// 新元素入栈
stack = append(stack, num)
}
for i, num := range nums1 {
if _, ok := mp[num]; ok {
res[i] = mp[num]
} else {
res[i] = -1
}
}
return res
}
2.下一个更大元素 II
2.1 题目描述
给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字
$x$
的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出$-1$
。
输入: [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数;
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。
2.2 解题思路
循环两遍数组,单调栈。
func nextGreaterElements(nums []int) []int {
n := len(nums)
stack := make([]int, 0)
res := make([]int, n)
for i := range res {
res[i] = -1
}
for i := 0; i < 2*n-1; i++ {
// 出栈
for len(stack) > 0 && nums[i%n] > nums[stack[len(stack)-1]] {
res[stack[len(stack)-1]] = nums[i%n]
stack = stack[:len(stack)-1]
}
// 入栈
stack = append(stack, i%n)
}
return res
}
3. 每日温度
3.1 题目描述
请根据每日 气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用
$0$
来代替。
给定一个列表temperatures = [73, 74, 75, 71, 69, 72, 76, 73],
你的输出应该是[1, 1, 4, 2, 1, 1, 0, 0]。
3.2 解题思路
单调栈。
func dailyTemperatures(T []int) []int {
n := len(T)
stack := []int{}
res := make([]int, n)
for i := 0; i < n; i++ {
// 出栈
for len(stack) > 0 && T[i] > T[stack[len(stack)-1]] {
res[stack[len(stack)-1]] = i - stack[len(stack)-1]
stack = stack[:len(stack)-1]
}
// 入栈
stack = append(stack, i)
}
return res
}