[leetCode]42. 接雨水
动态规化
- 使用两个数组保存左边数字的最大值与右边数字的最大值
- 遍历数组中每个元素,该元素所在位置能接的雨水量为该元素左边界和右边界的最小值减去该位置柱子的高度
class Solution {
public int trap(int[] height) {
if (height == null || height.length < 3)
return 0;
int ans = 0;
int[] leftMaxArr = new int[height.length];
leftMaxArr[0] = height[0];
int[] rightMaxArr = new int[height.length];
rightMaxArr[height.length-1] = height[height.length-1];
for (int i = 1; i < leftMaxArr.length; ++i) {
leftMaxArr[i] = Math.max(leftMaxArr[i-1],height[i]);
}
for (int i = rightMaxArr.length - 2; i >=0; --i) {
rightMaxArr[i] = Math.max(rightMaxArr[i+1], height[i]);
}
for (int i = 1; i < height.length; i++) {
ans += Math.min(leftMaxArr[i], rightMaxArr[i]) - height[i];
}
return ans;
}
}
栈
遍历数组,使用一个栈保存可能形成低洼的柱子,当当前的柱子高度大于之前(栈顶)柱子高度时可以形成积水,计算积水大小进行累加
class Solution {
public int trap(int[] height) {
LinkedList<Integer> stack = new LinkedList<>();
int i = 0, ans = 0;
while (i < height.length) {
while (!stack.isEmpty() && height[i] > height[stack.peek()]) {
int top = stack.pop();
if (stack.isEmpty())
break;
int disteance = i - stack.peek() - 1;
int boundedHeight = Math.min(height[i],
height[stack.peek()]) - height[top];
ans += disteance * boundedHeight;
}
stack.push(i++);
}
return ans;
}
}
双指针
将数组以最大柱子划分为左右两部分。分别遍历左右两部分。
- 记录左边最大值,如果当前柱子高度小于其左边界则计算接雨量
- 记录右边最大值,如果当前柱子高度小于右边界则计算接雨量
class Solution {
public int trap(int[] height) {
int left = 0;
int right = height.length - 1;
int leftMax = 0, rightMax = 0;
int ans = 0;
while (left < right) {
if (height[left] < height[right]) {
if (height[left] > leftMax) {
leftMax = height[left];
} else {
ans += leftMax - height[left];
}
left++;
} else {
if (height[right] > rightMax) {
rightMax = height[right];
} else {
ans += rightMax - height[right];
}
right--;
}
}
return ans;
}
}