[leetcode][042] Trapping Rain Water (Java)
我在Github上新建了一个解答Leetcode问题的Project, 大家可以参考, 目前是Java 为主,里面有leetcode上的题目,解答,还有一些基本的单元测试,方便大家起步。
题目在这里: https://leetcode.com/problems/trapping-rain-water/
[标签] Array; Stack; Two Pointers
这个题我感觉很难,我自己是完全不会。下面贴的是别人想到的好方法,自己适当做了些简单调整。
我觉得,这个解法非常巧妙的使用了双向的 two pointers。用到的变量有左右两个指针,一个在最左边,一个在最右边,然后两个一起往中间走。在走的时候维护两个变量,left barrier 和 right barrier,即左边的挡板和右边的挡板。
用例子说明一下思路:
用leftBarrier 和 rightBarrier围成一个”盆地“。如果是leftBarrier的高度低于rightBarrier(如下图),那么固定右边一侧,尝试移动left指针,这时我们比较leftBarrier和height[left],如果是height[left]较小的话,我们知道leftBarrier 和 left之间的部分一定是可以积攒下雨水的,(图中红色标注的部分);如果是height[left]较大的话,那就更新leftBarrier。
为什么上面是固定右边一侧的rightBarrier呢?因为当rightBarrier > leftBarrier的时候,如果再遇到height[left] < leftBarrier的情形的话,那么leftBarrier 和 height[left] 之间形成的区域是可以积攒雨水的。
啊,说的好像很绕,但是道理就是这么个道理……看看如果以后有更好的解释方法再来更新吧……汗
1 public class Solution { 2 public int trap(int[] height) { 3 4 int left = 0; 5 int right = height.length - 1; 6 7 int leftBarrier = 0; 8 int rightBarrier = 0; 9 int result = 0; 10 11 while (left <= right) { 12 if (leftBarrier <= rightBarrier) { 13 // there could be a basin between leftBarrier and rightBarrier 14 // and left side is lower one 15 if (height[left] > leftBarrier) { 16 // update left barrier 17 leftBarrier = height[left]; 18 } else { 19 // trap water (leftBarrier - height[left]) * 1 20 result += leftBarrier - height[left]; 21 } 22 left++; 23 } else { 24 if (height[right] > rightBarrier) { 25 // update right barrier 26 rightBarrier = height[right]; 27 } else { 28 // trap water (rightBarrier - height[right]) * 1 29 result += rightBarrier - height[right]; 30 } 31 right--; 32 } 33 } 34 return result; 35 } 36 }