接雨水-leetcode

题目描述

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

    示例 1:

    img

    输入: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. 初始化左右指针分别指向数组的首尾
  2. 初始化左右最大高度为0
  3. 当左指针小于右指针时循环:
    • 如果左指针高度小于右指针高度:
      • 如果左指针高度大于等于左最大高度,更新左最大高度
      • 否则,计算当前位置能存储的雨水量并累加
      • 左指针右移
    • 否则:
      • 如果右指针高度大于等于右最大高度,更新右最大高度
      • 否则,计算当前位置能存储的雨水量并累加
      • 右指针左移

代码:

import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

public class leetcode_007{


    public static int trap(int[] height) {
        if (height == null || height.length == 0) return 0;

        int left = 0, right = height.length - 1;
        int leftMax = 0, rightMax = 0;
        int water = 0;

       while(left < right) {
           if (height[left] < height[right]) {
               if(height[left] > leftMax) {
                   leftMax=height[left];
               }else{
                   water+=leftMax-height[left];
               }
               left++;
           }else{
               if(height[right] > rightMax) {
                   rightMax=height[right];
               }else{
                   water+=rightMax-height[right];
               }
               right++;
           }
       }
       return water;

    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String[] line = sc.nextLine().split(",");
        int[] nums= Arrays.stream(line).mapToInt(Integer::parseInt).toArray();
        int result =trap(nums);
        System.out.println(result);
    }
}

想法

思路:

img

按行计算每行的水的容量。第一行找到两侧端点,端点之间小于1的地方可以容纳水。第二行找到两侧端点,端点之间高度小于2的地方可以容纳水,依次类推。该算法的时间复杂度为O(maxHeight*n),该算法在大数据的情况下运行时间超出。

代码:

import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

public class leetcode_007{
    public static int trap(int[] height) {
        if (height == null || height.length == 0) return 0;

        int maxHeight = Arrays.stream(height).max().getAsInt();
        int waterSum = 0;

        // 预处理:找到每层的第一个和最后一个非零位置
        for (int i = 1; i <= maxHeight; i++) {
            int left = -1, right = -1;

            // 找到当前层的左右边界
            for (int j = 0; j < height.length; j++) {
                if (height[j] >= i) {
                    left = j;
                    break;
                }
            }

            for (int j = height.length - 1; j >= 0; j--) {
                if (height[j] >= i) {
                    right = j;
                    break;
                }
            }

            // 计算当前层的雨水
            if (left != -1 && right != -1 && left < right) {
                for (int j = left + 1; j < right; j++) {
                    if (height[j] < i) {
                        waterSum++;
                    }
                }
            }
        }

        return waterSum;
    }
    
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String[] line = sc.nextLine().split(",");
        int[] nums= Arrays.stream(line).mapToInt(Integer::parseInt).toArray();
        int result =trap(nums);
        System.out.println(result);
    }
}
posted @ 2025-09-11 12:14  狐狸胡兔  阅读(43)  评论(0)    收藏  举报