给定 n 个非负整数暗示每个宽度为 1 的柱子的高度图,计算按此摆列的柱子,下雨之后能接几雨水。
示例 1:
输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 暗示的高度图,在那种情况下,能够接 6 个单元的雨水(蓝色部门暗示雨水)。
示例 2:
输入:height = [4,2,0,3,2,5]
输出:9
提醒:
n == height.length
1 <= n <= 2 * 104
0 <= height[i] <= 105
解题思绪:
1,办法一:垂曲切割
A,关于肆意位置i,承接的雨水更大量是,位置i左侧的更大值和右侧更大值中较小者和位置i的高度差
B,因而需要两个预处置数组,记录位置i的左侧更大值和右侧更大值
2,办法二:程度切割
A,我们能够维护一个递加的栈
B,若是栈顶元素比比当前元素小,栈顶元素出栈
C,比力左侧元素和当前元素中间二者较小者
D,高度就是较小者和栈顶元素之差
E,宽度就是当前坐标和左侧坐标之间的间隔
3,办法三:双指针
A,能够比力摆布两个位置的值,较小者挪动指针
B,更新最左和最右的更大值,因为挪动指针的单调性,所以若是挪动的是左指针,当前左侧更大值必然比右侧更大值小
C,若是当前值比左侧更大值小,成果就取二者差值
代码实现
计划一:
func trap(height []int) int { leftMax:=make([]int,len(height)) rightMax:=make([]int,len(height)) leftMax[0]=height[0] rightMax[len(height)-1]=height[len(height)-1] for i:=1;i<len(height);i++{ if height[i]>leftMax[i-1]{ leftMax[i]=height[i] }else{ leftMax[i]=leftMax[i-1] } if height[len(height)-1-i]>rightMax[len(height)-i]{ rightMax[len(height)-1-i]=height[len(height)-1-i] }else{ rightMax[len(height)-1-i]=rightMax[len(height)-i] } } //fmt.PRintln(leftMax,rightMax) var ans int for i:=0;i<len(height);i++{ if leftMax[i]>rightMax[i]{ ans+=rightMax[i]-height[i] }else{ ans+=leftMax[i]-height[i] } } return ans}计划二:
func trap(height []int) int { var stack []int ans:=0 for i,h:=range height{ for len(stack)>0 && height[stack[len(stack)-1]]<h{ top:=stack[len(stack)-1] stack=stack[:len(stack)-1] if len(stack)==0{ break } max:=stack[len(stack)-1] width:=i-max-1 if h<height[max]{ans+=width*(h-height[top]) }else{ans+=width*(height[max]-height[top]) } } stack=apPEnd(stack,i) } return ans}计划三:
func trap(height []int) int { left:=0 right:=len(height)-1 leftMax:=left rightMax:=right ans:=0 for left<right{ if height[left]<height[right]{ if height[left]>height[leftMax]{ leftMax=left }else{ ans+=height[leftMax]-height[left] } left++ }else{ if height[right]>height[rightMax]{ rightMax=right }else{ ans+=height[rightMax]-height[right] } right-- } } return ans}
发表评论