1.题目描述:
给定n个非负整数表示每个宽度为1的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
2.双指针:
每列雨水的高度,取决于该列左侧最高柱和右侧最高柱子中最小值。首尾不计入。
class Solution {
public int trap(int[] height) {
int res = 0;
for (int i = 1; i < height.length - 1; i++) {
int leftMax = 0;
int rightMax = 0;
for (int j = 0; j < i; j++) {
leftMax = Math.max(leftMax, height[j]);
}
for (int k = i + 1; k < height.length; k++) {
rightMax = Math.max(rightMax, height[k]);
}
if (Math.min(leftMax, rightMax) > height[i]) {
res += Math.min(leftMax, rightMax) - height[i];
}
}
return res;
}
}
3.动态规划:
在双指针求左右最高子柱时存在重复计算,可以使用两个一维数组记录当前柱的左右最高子柱。
class Solution {
public int trap(int[] height) {
int res = 0;
int[] leftMax = new int[height.length];
int[] rightMax = new int[height.length];
leftMax[0] = height[0];
for (int i = 1; i < height.length; i++) {//其实包含了自己,但是不影响结果
leftMax[i] = Math.max(height[i], leftMax[i - 1]);
}
rightMax[height.length - 1] = height[height.length - 1];
for (int i = height.length - 2; i >= 0; i--) {
rightMax[i] = Math.max(height[i], rightMax[i + 1]);
}
for (int i = 1; i < height.length - 1; i++) {
if (Math.min(leftMax[i], rightMax[i]) - height[i] > 0) {
res += Math.min(leftMax[i], rightMax[i]) - height[i];
}
}
return res;
}
}
4.单调栈:
栈顶到栈底从小到大。
class Solution {
public int trap(int[] height) {
int res = 0;
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < height.length; i++) {
while (!stack.isEmpty() && height[i] > height[stack.peek()]) {
int temp = stack.pop();
if (!stack.isEmpty()) {
int h = Math.min(height[i], height[stack.peek()]) - height[temp];
int w = i - stack.peek() - 1;
res += h * w;
}
}
stack.push(i);
}
return res;
}
}