接雨水问题被力扣归结到困难范畴,该题只是比较抽象,其实难度并不是很高,用动态规划算法即可。具体解析过程见代码注释部分
package likou;
/*
* 接雨水
* 题干:
* 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图
* 计算按此排列的柱子,下雨之后能接多少雨水
*/
public class Demo42 {
/*
* 解题思路:
* 要想计算每一个格子能装多少雨水,这也就以为着要计算每个格子对应的左边的高度以及右边的高度
* 再用高的减低的,当然还要减掉本身的高度,得要的净值才是能装的水的多少。
* 这里需要定义两个数组left[],right[],分别记录在第i个格子的位置,左边的最大值以及右边的最大值
* 在i位置时,如果left[i-1]和right[i+1]的高度都比height[i]要低时,则不会存水
* 否则就取left[i-1]和right[i+1]的较小值,再计算下和height[i]的差,即为存水量
*/
public int trap(int[] height) {
int length = height.length;
int sum = 0;
if(length == 1) {
return sum;
}else {
int[] left = new int[length];
left[0] = height[0];
int[] right = new int[length];
right[right.length-1] = height[length-1];
for(int i=1;i<length-1;i++) {
left[i] = Math.max(left[i-1],height[i]);
}
for(int j=length-2;j>0;j--) {
right[j] = Math.max(right[j+1], height[j]);
}
for(int k=1;k<length-1;k++) {
int temp = Math.min(left[k-1], right[k+1]);
int temp1 = temp - height[k];
if(temp1 > 0) {
sum +=temp1;
}
}
}
return sum;
}
/*
* 解题思路二:
* 维护两个指针,分别从左到右、从右到左进行遍历,分别记录最大高度
* 定义int leftMax,rightMax分别记录左边和右边的最大值
* leftMax初始值为0 rightMax初始值为0
*/
public int trapNew(int[] height) {
int length = height.length;
int sum = 0;
if(length ==1) {
return sum;
}else {
int left = 0, right = height.length - 1;
int leftMax = 0, rightMax = 0;
while (left < right) {
leftMax = Math.max(leftMax, height[left]);
rightMax = Math.max(rightMax, height[right]);
if (height[left] < height[right]) {
sum += Math.max(leftMax - height[left],0);
++left;
} else {
sum += Math.max(rightMax - height[right],0);
--right;
}
}
}
return sum;
}
public static void main(String args[]) {
Demo42 demo = new Demo42();
//3/int[] height = {4,2,3};
//0,1,0,2,1,0,1,3,2,1,2,1
int[] height = {6,4,2,0,3,2,0,3,1,4,5,3,2,7,5,3,0,1,2,1,3,4,6,8,1,3};
System.out.println(demo.trap(height));
System.out.println(demo.trapNew(height));
}
}