题目描述
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
示例 1:

1 2 3
| 输入:height = [0,1,0,2,1,0,1,3,2,1,2,1] 输出:6 解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。
|
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/trapping-rain-water
我的题解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| class Solution { public int trap(int[] height) { int len=height.length; int i=0,j=len-1,k=1; int sum=0; while(i<j) {
if(height[i]>=k&&height[j]>=k) { for(int x=i+1;x<j;x++) { if(height[x]<k) { sum++; } } k++; i=0; j=len-1; } else if(height[i]>=k) { j--; } else if(height[j]>=k) { i++; } else { j--; i++; } } return sum; } }
|
本题我的做法主要思想还是双指针,分别将双指针放在数组的最左边和最右边,观察图形可以一层一层的来看,先找到两端第一个大于等于1的方块,则在第一层这两个方块之间低于1的部分可以储存一份水,然后再看第二层(让k变成2),找到两端第一个大于等于2的方块,则在第二层这两个方块之间低于2的部分可以储存一份水(只记第二层的水,因为第一层已经记录了)。最后以此类推,直到两端找不到同时大于某个高度的数为止。
运行结果
执行用时:2739 ms, 在所有 Java 提交中击败了5.01%的用户
内存消耗:43.6 MB, 在所有 Java 提交中击败了5.02%的用户
通过测试用例:322 / 322
大神题解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| class Solution { public int trap(int[] walls) { if (walls == null || walls.length <= 2) { return 0; }
int water = 0; Stack<Integer> stack = new Stack<>(); for (int right=0; right<walls.length; right++) { while (!stack.isEmpty() && walls[right]>walls[stack.peek()]) {
int bottom = stack.pop();
if (stack.isEmpty()) { break; }
int left = stack.peek(); int leftHeight = walls[left]; int rightHeight = walls[right]; int bottomHeight = walls[bottom];
water += (right-left-1) * (Math.min(leftHeight, rightHeight)-bottomHeight); }
stack.push(right);
}
return water; } }
|
https://leetcode.cn/problems/trapping-rain-water/solution/trapping-rain-water-by-ikaruga/
引用自此评论区
该方法运用了栈的思想,先找到左边比右边矮的地方,于是此时栈的顶部就是凹陷地方,right就是右墙,再把栈顶元素取出,如果栈剩下的为空,则没有左墙直接跳出,如果有,假如凹陷的地方取出栈后,此时的栈左墙是和凹陷的地方一样高的(不可能比凹陷的地方矮,程序试从左到右找凹陷的),则由于water += (right-left-1) * (Math.min(leftHeight, rightHeight)-bottomHeight);
此时的水深度仍然算出来记录为零,由于while循环的存在,此时凹陷处会向左移动(栈顶元素取出了凹陷向左移动),直到找出左墙比凹陷高,此时就可以算出凹陷的水的格数了。但这种做法时间效率没有比我的做法效率提升多少,下面还有一种方法效率最好。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| class Solution { public int trap(int[] height) { int sum=0;
int index=0; for(int i=0;i<height.length;i++){ if(height[i]>height[index]){ index=i; } } int left=0; for(int i=1;i<index;i++){ if(height[i]<height[left]){ sum+=height[left]-height[i]; }else if(height[i]>=height[left]){ left=i; } }
int right=height.length-1; for(int i=height.length-2;i>index;i--){ if(height[i]<height[right]){ sum+=height[right]-height[i]; }else if(height[i]>=height[right]){ right=i; } } return sum; } }
|
来自提交答案时官方的标准解答
此方法是先找出图像的最高点,然后由此分成左右两个部分,这样每一列水的格数就取决于两边短板的高度了,小于短板高度就可以存储雨水,最后加起来,此算法我觉得很简单,效率也表现出来了最优。