给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。
42. 接雨水(栈,暴力)2 - 图1
示例:
输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6

解法一:栈

42. 接雨水(栈,暴力)2 - 图2
42. 接雨水(栈,暴力)2 - 图3
42. 接雨水(栈,暴力)2 - 图4
42. 接雨水(栈,暴力)2 - 图5
42. 接雨水(栈,暴力)2 - 图6
42. 接雨水(栈,暴力)2 - 图7
42. 接雨水(栈,暴力)2 - 图8
42. 接雨水(栈,暴力)2 - 图9
42. 接雨水(栈,暴力)2 - 图10
42. 接雨水(栈,暴力)2 - 图11
代码:

  1. public class Solution {
  2. public int trap(int[] height) {
  3. int sum = 0;
  4. Stack<Integer> stack = new Stack<>();
  5. int current = 0;
  6. while (current < height.length) {
  7. //如果栈不空并且当前指向的高度大于栈顶高度就一直循环
  8. while (!stack.empty() && height[current] > height[stack.peek()]) {
  9. int h = height[stack.peek()]; //取出要出栈的元素
  10. stack.pop(); //出栈
  11. if (stack.empty()) { // 栈空就出去
  12. break;
  13. }
  14. int distance = current - stack.peek() - 1; //两堵墙之前的距离。
  15. int min = Math.min(height[stack.peek()], height[current]);
  16. sum = sum + distance * (min - h);
  17. }
  18. stack.push(current); //当前指向的墙入栈
  19. current++; //指针后移
  20. }
  21. return sum;
  22. }
  23. }

42. 接雨水(栈,暴力)2 - 图12

解法二:暴力

  1. public class Solution {
  2. public int trap(int[] height){
  3. int a = 0;
  4. int b = height.length-1;
  5. int max = 0;
  6. int leftmax = 0;
  7. int rightmax = 0;
  8. while (a <= b) {
  9. leftmax = Math.max(leftmax,height[a]);
  10. rightmax = Math.max(rightmax,height[b]);
  11. if (leftmax < rightmax) {
  12. max += (leftmax-height[a]);
  13. a++;
  14. } else {
  15. max += (rightmax-height[b]);
  16. b--;
  17. }
  18. }
  19. return max;
  20. }
  21. }

42. 接雨水(栈,暴力)2 - 图13