42. 接雨水

image.png

  1. //双指针,最优解法
  2. func trap(height []int) int {
  3. if len(height) == 0 {
  4. return 0
  5. }
  6. left, right := 0, len(height)-1
  7. leftmax, rightmax := height[0], height[len(height)-1]
  8. var res int
  9. for ;left < right; {
  10. if rightmax > leftmax {
  11. res += leftmax - height[left]
  12. left ++
  13. if height[left] > leftmax {
  14. leftmax = height[left]
  15. }
  16. } else {
  17. res += rightmax - height[right]
  18. right--
  19. if height[right] > rightmax {
  20. rightmax = height[right]
  21. }
  22. }
  23. }
  24. return res
  25. }

双指针 时间O(N) 空间O(1)

在上述的动态规划方法中,我们用二维数组来存储每个柱子左右两侧的最大高度,但我们递推累加每个柱子的储水高度时其实只用到了 dp[i][0]dp[i][1] 两个值,因此我们递推的时候只需要用 int leftMax int rightMax 两个变量就行了。
即将上述代码中的递推公式:
res += Math.min(dp[i][0], dp[i][i1]) - height[i];
优化成:
res += Math.min(leftMax, rightMax) - height[i];
注意这里的 leftMax 是从左端开始递推得到的,而 rightMax 是从右端开始递推得到的。
因此遍历每个柱子,累加每个柱子的储水高度时,也需要用 leftright 两个指针从两端开始遍历。