42. Trapping Rain Water

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]
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值