503.下一个更大元素II
思路
本篇我侧重与说一说,如何处理循环数组。
相信不少同学看到这道题,就想那我直接把两个数组拼接在一起,然后使用单调栈求下一个最大值不就行了!
确实可以!
将两个nums数组拼接在一起,使用单调栈计算出每一个元素的下一个最大值,最后再把结果集即result数组resize到原数组大小就可以了。
这种写法确实比较直观,但做了很多无用操作,例如修改了nums数组,而且最后还要把result数组resize回去。
resize倒是不费时间,是O(1)的操作,但扩充nums数组相当于多了一个O(n)的操作。
其实也可以不扩充nums,而是在遍历的过程中模拟走了两边nums。
思路代码
func nextGreaterElements(nums []int) []int {
res:=make([]int,len(nums))
for i:=range res{
res[i]=-1
}
stack:=[]int{}
nums2:=append(nums,nums...)
for i,v:=range nums2{
for len(stack)>0&&v>nums2[stack[len(stack)-1]]{
if stack[len(stack)-1]<len(nums){
res[stack[len(stack)-1]]=v
}
stack=stack[:len(stack)-1]
}
stack=append(stack,i)
}
return res
}
官方代码
func nextGreaterElements(nums []int) []int {
length := len(nums)
result := make([]int,length,length)
for i:=0;i<len(result);i++{
result[i] = -1
}
//单调递减,存储数组下标索引
stack := make([]int,0)
for i:=0;i<length*2;i++{
for len(stack)>0&&nums[i%length]>nums[stack[len(stack)-1]]{
index := stack[len(stack)-1]
stack = stack[:len(stack)-1] // pop
result[index] = nums[i%length]
}
stack = append(stack,i%length)
}
return result
}
42. 接雨水
思路
如果当前遍历的元素(柱子)高度大于栈顶元素的高度,此时就出现凹槽了
取栈顶元素,将栈顶元素弹出,这个就是凹槽的底部,也就是中间位置,下标记为mid,对应的高度为height[mid](就是图中的高度1)。
此时的栈顶元素st.top(),就是凹槽的左边位置,下标为st.top(),对应的高度为height[st.top()](就是图中的高度2)。
当前遍历的元素i,就是凹槽右边的位置,下标为i,对应的高度为height[i](就是图中的高度3)。
此时大家应该可以发现其实就是栈顶和栈顶的下一个元素以及要入栈的元素,三个元素来接水!
那么雨水高度是 min(凹槽左边高度, 凹槽右边高度) - 凹槽底部高度,代码为:int h = min(height[st.top()], height[i]) - height[mid];
雨水的宽度是 凹槽右边的下标 - 凹槽左边的下标 - 1(因为只求中间宽度),代码为:int w = i - st.top() - 1 ;
当前凹槽雨水的体积就是:h * w。
求当前凹槽雨水的体积代码如下:
while (!st.empty() && height[i] > height[st.top()]) { // 注意这里是while,持续跟新栈顶元素
int mid = st.top();
st.pop();
if (!st.empty()) {
int h = min(height[st.top()], height[i]) - height[mid];
int w = i - st.top() - 1; // 注意减一,只求中间宽度
sum += h * w;
}
}
思路代码
func trap(height []int) int {
stack:=[]int{}
res:=0
for i:=0;i<len(height);i++{
for len(stack)>0&&height[i]>height[stack[len(stack)-1]]{
mid:=stack[len(stack)-1]
stack=stack[:len(stack)-1]
if len(stack)>0{
h:=min(height[stack[len(stack)-1]],height[i])-height[mid]
w:=i-stack[len(stack)-1]-1
res+=h*w
}
}
stack=append(stack,i)
}
return res
}
func min(i,j int)int{
if i<j{
return i
}
return j
}
困难
凹槽的计算是需要比较左右两侧最小值的,宽度通过下标计算。文章来源:https://www.toymoban.com/news/detail-539128.html
今日收获
接雨水问题,凹槽用单调栈计算。文章来源地址https://www.toymoban.com/news/detail-539128.html
到了这里,关于单调栈part2 | ● 503.下一个更大元素II ● 42. 接雨水的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!