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

输入: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.length1 <= n <= 2 * 1040 <= height[i] <= 105
解法
思路:
雨水容量由左右两侧较矮的边界决定。我们使用两个指针从数组两端向中间移动,同时跟踪左右两边的最大高度。
左指针的高度小于右指针时,水高度由左指针决定,左侧每个位置计算水的容量,每个位置水的容量是左侧最大的高度与当前位置的高度差。
步骤:
- 初始化左右指针分别指向数组的首尾
- 初始化左右最大高度为0
- 当左指针小于右指针时循环:
- 如果左指针高度小于右指针高度:
- 如果左指针高度大于等于左最大高度,更新左最大高度
- 否则,计算当前位置能存储的雨水量并累加
- 左指针右移
- 否则:
- 如果右指针高度大于等于右最大高度,更新右最大高度
- 否则,计算当前位置能存储的雨水量并累加
- 右指针左移
- 如果左指针高度小于右指针高度:
代码:
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);
}
}
想法
思路:

按行计算每行的水的容量。第一行找到两侧端点,端点之间小于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);
}
}

浙公网安备 33010602011771号