给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
- 很容易发现对于每一列,他所能承载的雨水量取决他左边所有柱子的最高值,右边所有柱子的最高值,并且二者取最小值。
- 可以利用DP分别求出每一个点的对应的左侧最高值和右侧最高值,但是这需要额外的空间来保存。
- 需要注意到取二者最高值的最小值的条件还没有用到。
可以设left_max指向当前left指针所指柱子左侧最高值(不包括left柱子本身),right_max指向当前right指针所指柱子右侧的最高值(不包括right柱子本身)。初始时left指向第一个柱子,right指向最后一个柱子。
关键思路
- left_max和right_max两者总会有一个大小关系。
- 当left_max>=right_max时,指针right所指柱子左侧的最大值一定会比left_max大,因此right柱子指针左侧的最大值和右侧的最大值二者间的较小值一定会取决于right_max;于是可以将right指针可以承载的雨水数量计算出,并放心大胆地移动向左移动right指针。
- 反之亦然
于是,直到right和left相遇,即求出了结果。
AC代码如下
public int trap(int[] height) {
int left_max = 0;
int right_max = 0;
int left = 0;
int right = height.length - 1;
int ret =0 ;
while(left<=right)
{
if(left_max < right_max)
{
ret += Math.max((left_max - height[left]) , 0);
left_max = Math.max(left_max , height[left]);
left++;
}
else
{
ret += Math.max((right_max - height[right]) , 0);
right_max = Math.max(right_max,height[right]);
right--;
}
}
return ret;
}