$$ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Self-defined math definitions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Math symbol commands \newcommand{\intd}{\,{\rm d}} % Symbol 'd' used in integration, such as 'dx' \newcommand{\diff}{{\rm d}} % Symbol 'd' used in differentiation ... $$

42. 接雨水

题目描述查看:https://leetcode-cn.com/problems/trapping-rain-water/

  题目的意思是给定一个数组,数组值表示柱子的高度,问能盛多少水。

 

 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。

  • 思路

  按照列来看,每一列能盛多少水,取决于它左边柱子的最大值leftMax和右边柱子的最大值rightMax,leftMax和rightMax里小的那个又决定水能有多高(木桶,能装多少水,短的说了算)。根据这个思路,只要知道每个柱子左边的最大值leftMax和右边的最大值rightMax,就能求解能装多少水了。

leftMax和rightMax的求解

 1         leftMax[0] = height[0];
 2         rightMax[height.length-1] = height[height.length-1];
 3         //比当前柱子和前一个柱子的leftMax,找到当前柱子的左最大值
 4         for (int i = 1; i < height.length-1; i++) {
 5             leftMax[i] = Math.max(leftMax[i-1],height[i]);
 6         }
 7         //右最大值是从当前柱子往右比,所以要从最右边的开始求
 8         //比当前柱子和前一个柱子的rightMax,找到当前柱子的右最大值
 9         for (int i = height.length -2;i > 0; i--) {
10             rightMax[i] = Math.max(rightMax[i+1],height[i]);
11         }
  • 边界条件

2个元素,没法装水。

if(height.length < 3)return 0;

3个元素,装水值取决于height[0]和height[2]的高度,如果height[1]>=min(height[0],height[2]),没法装水。

if(height.length == 3)return Math.min(height[0],height[2]) - height[1] > 0 ?Math.min(height[0],height[2]) - height[1]:0;
  • 代码

 1     public int trap(int[] height) {
 2         int[] leftMax = new int[height.length];
 3         int[] rightMax = new int[height.length];
 4         if(height.length < 3)return 0;
 5         if(height.length == 3)return Math.min(height[0],height[2]) - height[1] > 0 ?Math.min(height[0],height[2]) - height[1]:0;
 6         int water = 0;
 7         leftMax[0] = height[0];
 8         rightMax[height.length-1] = height[height.length-1];
 9         //比当前柱子和前一个柱子的leftMax,找到当前柱子的左最大值
10         for (int i = 1; i < height.length-1; i++) {
11             leftMax[i] = Math.max(leftMax[i-1],height[i]);
12         }
13         //右最大值是从当前柱子往右比,所以要从最右边的开始求
14         //比当前柱子和前一个柱子的rightMax,找到当前柱子的右最大值
15         for (int i = height.length -2;i > 0; i--) {
16             rightMax[i] = Math.max(rightMax[i+1],height[i]);
17         }
18 
19         for (int i = 1; i < height.length - 1; i++) {
20             int h = Math.min(leftMax[i],rightMax[i]);
21             if(h > height[i])water += h- height[i];
22         }
23         return water;
24     }

 

posted @ 2020-04-02 12:11  V丶vvv  阅读(198)  评论(0编辑  收藏  举报