- 接雨水
给定 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
class Solution {
// 1. 按行求 (会超时)
/**
public int trap(int[] height) {
int sum = 0;
int max = getMax(height); // 获取最大高度
for(int i = 1; i <= max;i++){
boolean change = false; // 标记temp是否应该改变
int temp = 0;
for(int j = 0; j < height.length;j++){
if(change && height[j] < i){
temp++;
}
if(height[j] >= i){
sum = sum + temp;
temp = 0;
change = true;
}
}
}
return sum;
}
public int getMax(int[] height){
int max = 0;
for(int i = 0; i < height.length;i++){
if(max < height[i]){
max = height[i];
}
}
return max;
}
*/
/**
// 2. 按列求
public int trap(int[] height) {
int sum = 0;
// 第一列和最后一列一定不会有雨水
for(int i = 1; i < height.length - 1;i++){
// 求左边最高的列
int max_left = 0;
for(int j = i - 1; j >= 0;j--){
if(max_left < height[j]){
max_left = height[j];
}
}
// 求右边最高的列
int max_right = 0;
for(int j = i+1; j < height.length; j++){
if(max_right < height[j]){
max_right = height[j];
}
}
//求两边最高的列中的最低的列
int min = Math.min(max_left,max_right);
if(min > height[i]){
sum += (min - height[i]);
}
}
return sum;
}
*/
/** 3. 动态规划
(使用2个数组保存左边最高的墙和右边最高的墙)
*/
/**
public int trap(int[] height) {
int[] max_left = new int[height.length];
int[] max_right = new int[height.length];
int sum = 0;
// 求出左边最高的墙
for(int i = 1; i < height.length - 1;i++){
max_left[i] = Math.max(max_left[i-1],height[i-1]);
}
// 求出右边最高的墙
for(int j = height.length - 2; j >= 0;j--){
max_right[j] = Math.max(max_right[j+1],height[j+1]);
}
for(int k = 1;k < height.length - 1;k++){
// 求出左右两边比较低的墙
int min = Math.min(max_left[k],max_right[k]);
if(min > height[k]){
sum = sum + (min - height[k]);
}
}
return sum;
}
*/
// 4. 双指针
public int trap(int[] height) {
int sum = 0;
int max_left = 0;
int max_right = 0;
int left = 1;
int right = height.length - 2; // 加右指针进去
for (int i = 1; i < height.length - 1; i++) {
//从左到右更
if (height[left - 1] < height[right + 1]) {
max_left = Math.max(max_left, height[left - 1]);
int min = max_left;
if (min > height[left]) {
sum = sum + (min - height[left]);
}
left++;
//从右到左更
} else {
max_right = Math.max(max_right, height[right + 1]);
int min = max_right;
if (min > height[right]) {
sum = sum + (min - height[right]);
}
right--;
}
}
return sum;
}
}