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

    示例 1:
    image.png

    输入: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 个单位的雨水(蓝色部分表示雨水)。
    示例 2:

    输入:height = [4,2,0,3,2,5]
    输出:9

    提示:

    n == height.length
    1 <= n <= 2 * 104
    0 <= height[i] <= 105


    单调栈

    1. class Solution {
    2. int[] stk;
    3. int tt;
    4. public int trap(int[] height) {
    5. int n = height.length;
    6. stk = new int[n+1];
    7. int res = 0;
    8. for(int i = 0; i < n; ++i){
    9. while(tt > 0 && height[stk[tt]] < height[i]){
    10. int curHeight = height[stk[tt--]];
    11. if(tt <= 0) break; //边界最后一个是没法接雨水的
    12. int l = stk[tt]; //左边柱子
    13. int r = i;
    14. int h = Math.min(height[l],height[r]) - curHeight;
    15. res += h * (r-l-1);
    16. }
    17. stk[++tt] = i;
    18. }
    19. return res;
    20. }
    21. }

    双指针
    image.png

    1. class Solution {
    2. public int trap(int[] height) {
    3. int n = height.length;
    4. int max_right = 0, max_left = 0;
    5. int left = 1, right = n-2;
    6. int res = 0;
    7. for(int i = 1; i < n-1; ++i){
    8. //从左往右更新
    9. if(height[left-1] < height[right+1]){
    10. max_left = Math.max(max_left,height[left-1]);
    11. int min = max_left;
    12. if(min > height[left])
    13. res += min - height[left];
    14. left++;
    15. }
    16. //从右往左更新
    17. else{
    18. max_right = Math.max(max_right,height[right+1]);
    19. int min = max_right;
    20. if(min > height[right])
    21. res += min - height[right];
    22. right--;
    23. }
    24. }
    25. return res;
    26. }
    27. }