// 单调栈
// 时间复杂度 : O(n)
// 空间复杂度 : O(n)
public int trap(int[] height) {
int ans = 0;
Deque<Integer> s = new ArrayDeque<>();
for (int i = 0; i < height.length; i++) {
while (!s.isEmpty() && height[s.peek()] < height[i]) {
int top = s.poll();
if (s.isEmpty()) break;
int left = s.peek();
int curWidth = i - left - 1;
int curHeight = Math.min(height[i], height[left]) - height[top];
ans += curHeight * curWidth;
}
s.push(i);
}
return ans;
}
// 双指针
// 时间复杂度 : O(n)
// 空间复杂度 : O(1)
public int trap(int[] height) {
int curH = 0, ans = 0;
int l = 0, r = height.length - 1;
while (l < r) {
if (height[l] <= height[r]) {
ans += Math.max(0, curH - height[l]);
curH = Math.max(curH, height[l]);
l++;
} else {
ans += Math.max(0, curH - height[r]);
curH = Math.max(curH, height[r]);
r--;
}
}
return ans;
}
题目详情可见 接雨水 II
木桶原则,从最外圈开始向内收缩
public int trapRainWater(int[][] heightMap) {
int m = heightMap.length, n = heightMap[0].length;
boolean[][] vis = new boolean[m][n];
Queue<int[]> q = new PriorityQueue<>((a, b) -> a[2] - b[2]);
for (int i = 0; i < m; i++) {
q.offer(new int[]{i, 0, heightMap[i][0]});
q.offer(new int[]{i, n - 1, heightMap[i][n - 1]});
vis[i][0] = true;
vis[i][n - 1] = true;
}
for (int i = 0; i < n; i++) {
q.offer(new int[]{0, i, heightMap[0][i]});
q.offer(new int[]{m - 1, i, heightMap[m - 1][i]});
vis[0][i] = true;
vis[m - 1][i] = true;
}
int[][] dirs = { {1, 0}, {-1, 0}, {0, 1}, {0, -1} };
int ans = 0;
while (!q.isEmpty()) {
int[] cur = q.poll();
for (int[] dir : dirs) {
int nx = cur[0] + dir[0], ny = cur[1] + dir[1];
if (nx < 0 || nx >= m || ny < 0 || ny >= n || vis[nx][ny]) continue;
ans += Math.max(0, cur[2] - heightMap[nx][ny]);
q.offer(new int[]{nx, ny, Math.max(cur[2], heightMap[nx][ny])});
vis[nx][ny] = true;
}
}
return ans;
}