题目:42. 接雨水
给定 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 个单位的雨水(蓝色部分表示雨水)。
示例 2:
输入:height = [4,2,0,3,2,5]
输出:9
提示:
n == height.length
0 <= n <= 3 * 10^4
0 <= height[i] <= 10^5
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/trapping-rain-water
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
- 暴力解法
- 动态规划
- 单调栈
- 双指针
解题代码
暴力解法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Solution { public int trap(int[] height) { int ans = 0; for (int i = 1; i < height.length - 1; i++) { int maxLeft = 0; int maxRight = 0; for (int j = i - 1; j >= 0; j--) { maxLeft = Math.max(maxLeft, height[j]); } for (int j = i + 1; j < height.length; j++) { maxRight = Math.max(maxRight, height[j]); } ans += Math.max(0, Math.min(maxLeft, maxRight) - height[i]); } return ans; } }
|
动态规划
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Solution { public int trap(int[] height) { int ans = 0; int[] maxLeft = new int[height.length]; int[] maxRight = new int[height.length]; for (int i = 1; i < height.length; i++) { maxLeft[i] = Math.max(maxLeft[i - 1], height[i - 1]); } for (int i = height.length - 2; i >= 0; i--) { maxRight[i] = Math.max(maxRight[i + 1], height[i + 1]); } for (int i = 1; i < height.length - 1; i++) { ans += Math.max(0, Math.min(maxLeft[i], maxRight[i]) - height[i]); } return ans; } }
|
官方解题代码
动态规划
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| class Solution { public int trap(int[] height) { int n = height.length; if (n == 0) { return 0; }
int[] leftMax = new int[n]; leftMax[0] = height[0]; for (int i = 1; i < n; ++i) { leftMax[i] = Math.max(leftMax[i - 1], height[i]); }
int[] rightMax = new int[n]; rightMax[n - 1] = height[n - 1]; for (int i = n - 2; i >= 0; --i) { rightMax[i] = Math.max(rightMax[i + 1], height[i]); }
int ans = 0; for (int i = 0; i < n; ++i) { ans += Math.min(leftMax[i], rightMax[i]) - height[i]; } return ans; } }
|
单调栈
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class Solution { public int trap(int[] height) { int ans = 0; Deque<Integer> stack = new LinkedList<Integer>(); int n = height.length; for (int i = 0; i < n; ++i) { while (!stack.isEmpty() && height[i] > height[stack.peek()]) { int top = stack.pop(); if (stack.isEmpty()) { break; } int left = stack.peek(); int currWidth = i - left - 1; int currHeight = Math.min(height[left], height[i]) - height[top]; ans += currWidth * currHeight; } stack.push(i); } return ans; } }
|
双指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Solution { public int trap(int[] height) { int ans = 0; int left = 0, right = height.length - 1; int leftMax = 0, rightMax = 0; while (left < right) { leftMax = Math.max(leftMax, height[left]); rightMax = Math.max(rightMax, height[right]); if (height[left] < height[right]) { ans += leftMax - height[left]; ++left; } else { ans += rightMax - height[right]; --right; } } return ans; } }
|