题目
方法一:动态规划
public class Trap {
public int trap(int[] height) {
//动态规划
//下标i能存多少水和i两边的最大高度有关,i处能存的水=两边最大高度的最小值-i的高度。
//i的存水值需要分别找到左右两边的最大高度,每个都要查一遍时间复杂度是on方。
//最理想的情况是知道i的左右两边即i-1和i+1的最大高度是多少,这样就不用每次都查一遍了,直接取i-1和i+1就好。
//所以定义两个数组leftMax和rightMax分别存当前下标到最左边和最右边最大的高度值。
int len = height.length;
int leftMax[] = new int[len];
int rigthMax[] = new int[len];
leftMax[0]=height[0];//最右边最大高度已知
for (int i = 1; i < len; i++) {
leftMax[i] = Math.max(height[i], leftMax[i-1]);
}
rigthMax[len-1]=height[len-1];//最左边最大高度已知
for (int i = len-2; i >= 0; i--) {
rigthMax[i] = Math.max(height[i], rigthMax[i+1]);
}
int sum = 0;
//求每处最大的存水量
for (int i = 0; i < len; i++) {
sum += Math.min(leftMax[i], rigthMax[i]) - height[i];
}
return sum;
}
public static void main(String[] args) {
Trap trap = new Trap();
//int[] height = {0,1,0,2,1,0,1,3,2,1,2,1};
int[] height = {4,2,0,3,2,5};
System.out.println(trap.trap(height));
}
}
LeetCode测试结果
方法二:双指针
public class Trap {
public static void main(String[] args) {
Trap trap = new Trap();
//int[] height = {0,1,0,2,1,0,1,3,2,1,2,1};
int[] height = {4,2,0,3,2,5};
System.out.println(trap.trap(height));
}
public int trap(int[] height) {
//双指针
//维护两个指针l和r,两个变量lm和rm
//l只能往左移动,r只能往右移动lm记录左侧的最大高度,rm记录右侧的最大高度
//当height[l]>height[r]那么lm>rm,那r处存水=rm-height[r]
//l处存水同理
int l = 0, r = height.length-1;
int lm = 0, rm = 0;
int sum = 0;
//求每处最大的存水量
while (r>l) {
lm = Math.max(lm, height[l]);
rm = Math.max(rm, height[r]);
if (height[l]>height[r]) {
sum += rm-height[r];
r--;
} else {
sum += lm-height[l];
l++;
}
}
return sum;
}
}
LeetCode测试结果