42. Trapping Rain Water
Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.
The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. Thanks Marcos for contributing this image!
Example:
Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/trapping-rain-water
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
Think and method:
There are many solutions to this problem, which took me a long time to understand and verify.The general idea is that for each element in the array, we subtract the current height from the smaller value of the height on both sides to determine how much rain water we can hold (of course, this process starts with the second element of the array and ends with the penultimate element).
1. Violent law
In fact, this is the first method, directly according to the idea of violent solution, the detailed algorithm process does not do the formula elaboration, in the code can also be very clear.
Time complexity: O(n^2)
Space complexity: O(1)
2. Dynamic programming
In violence law exactly the same way, only in the violent method, each of us to consider the capacity of a location, you need to traverse the entire array, then we can use two traverse these these values stored in advance about maximum value of I, in the final again scanning, a violent method to realize the process of n times, save a lot of time, of course, it will have some loss on the space.
Time complexity: O(n). From the above analysis, we can see that the time consumption has been greatly reduced
Space complexity: O(n), storage inevitably brings space consumption
3. Double pointer
Further optimization, we still used twice traversal in 2, how to reduce it to once, double pointer is the best solution, which is also my favorite method.
From both sides, take the left pointer as an example. Compared with the height on the right, if the current water level is higher than the maximum value on the left, update the maximum value on the left; otherwise, the current water amount can be calculated by subtraction.The right pointer is the opposite.Traverse.
Time complexity: O(n).
Space complexity: O(1).
4.stack
See the code comments for the specific algorithm. The basic idea is:
If the current bar is less than or equal to the top bar, we push the index of the bar.If we find a bar that is longer than the top of the stack, we can pop the top element and add up the answers
Time complexity: O(n).
Space complexity: O(n).
Codes:
1、
func trap(height []int)int{
length :=len(height)
result :=0
for i:=1;i < length - 1;i++{
leftMax := 0
//Scan and update from the current element to the left
for k := i;k >= 0;k--{
leftMax =max(height[k],leftMax)
}
//Scan and update from the current element to the right
rightMax :=0
for j:=i;j < length;j++{
rightMax =max(height[j],rightMax)
}
//add it
minval := min(leftMax,rightMax)
water := minval-height[i]
result = result + water
}
return result
}
func max(a,b int)int{
if a>b{
return a
}
return b
}
func min(a,b int)int{
if a>b{
return b
}
return a
}
2、
func trap(height []int)int{
if len(height)==0{
return 0
}
length :=len(height)
res :=0
leftmax :=make([]int,length)
rightmax :=make([]int,length)
leftmax[0]= height[0]
rightmax[length-1] = height[length-1]
//Find left_max
for i:=1;i < length;i++{
leftmax[i] = max(leftmax[i-1],height[i])
}
//Find right_max
for i:= length - 2;i>=0;i--{
rightmax[i] = max(rightmax[i+1],height[i])
}
//scan
for i:=1;i < length - 1;i++{
waterval := min(leftmax[i],rightmax[i]) - height[i]
res += waterval
}
return res
}
func max(a,b int)int{
if a>b{
return a
}
return b
}
func min(a,b int)int{
if a>b{
return b
}
return a
}
3、
func trap(height []int) int {
var leftMax, rightMax int
result := 0
left := 0
right := len(height) - 1
//if left == right finish
for left < right {
if height[left] < height[right] {
if height[left] > leftMax {
//refresh leftmax
leftMax = height[left]
} else {
//pillar is taller than water surface so must have water
result += leftMax - height[left]
}
//consider next column
left++
} else {
if height[right] >= rightMax {
//refresh rightmax
rightMax = height[right]
} else {
//pillar is taller than water surface so must have water
result += rightMax - height[right]
}
//consider next column
right--
}
}
return result
}
4、
func trap(height []int) int {
stack := make([]int, 0)
result := 0
current := 0
for current < len(height) {
for len(stack) != 0 && height[current] > height[stack[len(stack)-1]] {
//Pop up the stack
top := stack[len(stack)-1]
stack = stack[:len(stack)-1]
if len(stack) == 0 {
break
}
//calculate distance
distance := current - stack[len(stack)-1] - 1
//calculate height
h := min(height[current],height[stack[len(stack)-1]]) - height[top]
//calculate result
result += distance * h
}
stack = append(stack, current)
current++
}
return result
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
Test:
Example:
Input: [0,1,0,2,1,0,1,3,2,1,2,1]
special situation:
Input:[1,0]