给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
这题一看就不会,直接放弃看答案。答案都有点看不懂,后面一边debug一边一步一步对照LeetCode那个12/12的ppt,勉强理解了这道题的思想。我只看了双指针的解答。
官方题解
我个人理解是这样的。
随便选一根柱子,它能接多少水是由什么决定的?是它左边最高的柱子和右边最高的柱子中矮的那个决定的。比如这个水柱,就是它左边最高为1,右边最高为3,决定了它最多只能接1。但是使用双指针,左边从0开始往后移动,右边从n-1开始向左移动,debug可以发现,在找这个水柱的位置的过程中,我们找到的左边最高确实是1,右边根本还没发现它最高为3,只发现当前右边最高为2。这会影响它的计算结果吗?经过推论是不会的。为什么呢?前面说到我们只需要找它左最高和右最高小的那个就行了。右边虽然不是真正的最高,但是如果这个左最高比目前找到的右最高还小,那即使当前找到的右最高不是全局的右最高也是对的。
if (height[left] < height[right]) {
ans += leftMax - height[left];
++left;
}
这一段是什么意思呢? ans += leftMax - height[left]; 就是说左最高小于当前右最高了,能接多少水由左最高决定。为什么是这个判断条件。如果只有当前左指针的高度小于当前右指针的高度时,左指针才会往后走。反之右指针往前走。那么,走的那个指针就是上一次比高度没比过的。它走了,另一边不动,不动的那个指针指向的一定是左右指针目前走过的最高峰。(比如左边一直比右边小,左边一直比不过就一直往后走,直到遇到个高的记作x,能比过右边了,那左指针指向的就是左右最高的,此时右边为了比过x就往前走,直到遇到个高的y能比过x了,此时y就是左右指针走过所有路中最高的)所以上面那一小段代码,就是左指针走,右指针目前指向的是左右指针走过的最高峰,那么目前的右最高是大于左最高的,所以能接多少水由左最高决定。
另外一半代码同样推论
关键是理解,停下来的时候的指针指向的已经是左右指针走过所有路中最高的了。
class Solution {
public int trap(int[] height) {
int ans = 0;
int left = 0, right = height.length - 1;
int leftMax = 0, rightMax = 0;
while (left < right) {
leftMax = Math.max(leftMax, height[left]);
rightMax = Math.max(rightMax, height[right]);
if (height[left] < height[right]) {
ans += leftMax - height[left];
++left;
} else {
ans += rightMax - height[right];
--right;
}
}
return ans;
}
}
作者:力扣官方题解
链接:https://leetcode.cn/problems/trapping-rain-water/solutions/692342/jie-yu-shui-by-leetcode-solution-tuvc/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。