102 lines
3.3 KiB
Java
102 lines
3.3 KiB
Java
|
package stack;
|
|||
|
|
|||
|
import java.util.Deque;
|
|||
|
import java.util.LinkedList;
|
|||
|
|
|||
|
/**
|
|||
|
* 题目: 42. 接雨水 (trap)
|
|||
|
* 描述:给定 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 个单位的雨水(蓝色部分表示雨水)。
|
|||
|
*
|
|||
|
* 链接:https://leetcode.cn/problems/trapping-rain-water/
|
|||
|
*/
|
|||
|
//困难题 不会
|
|||
|
public class Trap {
|
|||
|
//暴力解法
|
|||
|
public int trap1(int[] height) {
|
|||
|
int sum = 0;
|
|||
|
for (int i = 0; i < height.length; i++) {
|
|||
|
// 第一个柱子和最后一个柱子不接雨水
|
|||
|
if (i == 0 || i == height.length - 1) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
int rHeight = height[i]; // 记录右边柱子的最高高度
|
|||
|
int lHeight = height[i]; // 记录左边柱子的最高高度
|
|||
|
|
|||
|
for (int r = i + 1; r < height.length; r++) {
|
|||
|
if (height[r] > rHeight) {
|
|||
|
rHeight = height[r];
|
|||
|
}
|
|||
|
}
|
|||
|
for (int l = i - 1; l >= 0; l--) {
|
|||
|
if (height[l] > lHeight) {
|
|||
|
lHeight = height[l];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
int h = Math.min(lHeight, rHeight) - height[i];
|
|||
|
if (h > 0) {
|
|||
|
sum += h;
|
|||
|
}
|
|||
|
}
|
|||
|
return sum;
|
|||
|
}
|
|||
|
//动态规划
|
|||
|
public int trap2(int[] height) {
|
|||
|
if (height.length <= 2) return 0;
|
|||
|
int n = height.length;
|
|||
|
int[] maxLeft = new int[n];
|
|||
|
int[] maxRight = new int[n];
|
|||
|
|
|||
|
// 记录每个柱子左边柱子最大高度
|
|||
|
maxLeft[0] = height[0];
|
|||
|
for (int i = 1; i < n; i++) {
|
|||
|
maxLeft[i] = Math.max(height[i], maxLeft[i - 1]);
|
|||
|
}
|
|||
|
|
|||
|
// 记录每个柱子右边柱子最大高度
|
|||
|
maxRight[n - 1] = height[n - 1];
|
|||
|
for (int i = n - 2; i >= 0; i--) {
|
|||
|
maxRight[i] = Math.max(height[i], maxRight[i + 1]);
|
|||
|
}
|
|||
|
|
|||
|
// 求和
|
|||
|
int sum = 0;
|
|||
|
for (int i = 1; i < n-1; i++) {
|
|||
|
int count = Math.min(maxLeft[i-1], maxRight[i+1]) - height[i];
|
|||
|
if (count > 0) {
|
|||
|
sum += count;
|
|||
|
}
|
|||
|
}
|
|||
|
return sum;
|
|||
|
}
|
|||
|
|
|||
|
//单调栈
|
|||
|
public int trap(int[] height) {
|
|||
|
int sum = 0;
|
|||
|
Deque<Integer> stack = new LinkedList<>();
|
|||
|
|
|||
|
for (int i = 0; i < height.length; i++) {
|
|||
|
// 当栈不为空且当前柱子的高度大于栈顶柱子的高度时
|
|||
|
while (!stack.isEmpty() && height[i] > height[stack.peek()]) {
|
|||
|
int top = stack.pop();
|
|||
|
// 如果栈为空,则没有左边的柱子来接雨水
|
|||
|
if (stack.isEmpty()) break;
|
|||
|
// 计算当前柱子与栈顶柱子之间的距离
|
|||
|
int distance = i - stack.peek() - 1;
|
|||
|
// 计算可以接的雨水高度:两边较低的高度减去中间柱子的高度
|
|||
|
int boundedHeight = Math.min(height[i], height[stack.peek()]) - height[top];
|
|||
|
sum += distance * boundedHeight;
|
|||
|
}
|
|||
|
// 将当前索引入栈
|
|||
|
stack.push(i);
|
|||
|
}
|
|||
|
return sum;
|
|||
|
}
|
|||
|
}
|