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
思路:
个人思路:
1、接水的条件?
这道题需要求两个柱子之间的雨水,所以可以采用双指针来表示左右柱子,关键在于怎么才能接到雨水?一个柱子肯定不行,所以柱子必须得两个!那么一开始左指针从最左边开始向右遍历,右指针从最右边开始向左遍历,所以起初的和结尾的柱子不能没有对应数组中第一个和最后一个元素不能为零,如果为零直接跳过
2、能接多少水?
在示例1中,左指针指向第二个元素1,右指针指向最后一个元素1,那么他们能接多少水?很明显两个柱子之间能有多少个零就能接多少水,因为接多少水看的是两个指针的最小值,由于两个指针是同样大小所以小于1即可,那么接完水后又该怎么办呢?我们不清楚中间还能接多少水,所以我们可以把接到的水填上柱子,柱子的高度取决于你取水的多少
比如示例一第一次取水之前是[0,1,0,2,1,0,1,3,2,1,2,1] 取水后:[0,1,1,2,1,1,1,3,2,1,2,1]
我的思路就是取完水后填充柱子
class Solution {public int trap(int[] height) {int left=0;int right=height.length-1;int count =0;while (left<right){if(height[left]==0){left++;}if(height[right]==0){right--;}int MinNum=Math.min(height[left],height[right]);for(int i= left;i+1<right;i++){if(height[i+1]<MinNum){count+=MinNum-height[i+1];height[i+1]=MinNum;}}if (height[left]<=height[right]){left++;}else {right--;}}return count;}}
写了2小时击败5%哈哈哈哈哈(狗头)
官方思路:
1、如何计算雨水?
左(右)指针的最大值 - 当前左(右)指针的值=雨水的数量
2、计算哪一边的雨水呢?
比较一下左右指针的柱子高度,哪边矮就计算哪边的雨水(比较当前左右指针指向的元素大小,计算元素小的那边的雨水,然后再移动一位)
左边的雨水数量由左边的最大柱子计算,右边的雨水数量由右边的最大柱子计算,而计算之前是对比左右指针当前的柱子高度,选出矮的那边柱子进行计算
时间复杂度:O(n),其中 n 是数组 height 的长度。两个指针的移动总次数不超过 n。
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;}
}