接雨水-力扣热题100
题目:
给定 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
分析:
这道题其实画图什么的分析下来就一个公式:
当前柱子能接水的值=min(左边柱子最高值,右边柱子最高值)−当前柱子的值
让两个指向数组的left和right这两个变量即这两个指针在不相遇的时候就说明中间还有柱子没有计算,一直到两个指针相遇,那么就说明所有柱子都计算了,程序结束就好。
核心思想就是利用两个指针从两端向中间遍历,同时维护两个变量来记录从左到右和从右到左遍历时遇到的最大高度。对于数组中的每一个柱子,其能接的雨水量可以通过比较它与左侧和右侧最大高度的最小值来确定。
这是一个难度稍稍中等偏上的题目。
难点还是在于理解,只要理解了代码其实很简单。
我用的双指针法,还有栈的方法等,我感觉双指针法比较简单易于理解。
具体步骤如下:
1.初始化两个指针 left 和 right 分别指向数组的起始和结束位置,同时初始化两个变量 left_max 和 right_max 为数组的第一个和最后一个元素的高度。
2.当 left < right 时,执行以下操作:
如果 height[left] < height[right],则更新 left_max 为 max(left_max, height[left]),然后计算 left 位置的雨水量并累加到总雨水量中,接着将 left 指针向右移动。
如果 height[left] >= height[right],则更新 right_max 为 max(right_max, height[right]),然后计算 right 位置的雨水量并累加到总雨水量中,接着将 right 指针向左移动。
-
重复步骤2,直到 left 和 right 相遇。
class Solution {
public int trap(int[] height) {
//难在理解,有个公式:
//每个柱子能接的水的值=min(左边柱子最高值,右边柱子最高值)-当前柱子的值
if (height == null || height.length == 0)
return 0;
int left = 0;
int right = height.length - 1;
int left_max=0,right_max=0;
int water = 0;
while(left<right){
if(height[left]<height[right]){
left_max = Math.max(left_max,height[left]);
water+=left_max-height[left];
left++;
}else{
right_max = Math.max(right_max,height[right]);
water+=right_max-height[right];
right--;
}
}
return water;
}
}