版权声明:本文为博主原创文章,转载请注明出处。
个人博客地址:https://yangyuanlin.club
欢迎来踩~~~~
- 类似问题:容器最大容水量
题目描述
Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.
For example,
Given[0,1,0,2,1,0,1,3,2,1,2,1], return6.

The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. Thanks Marcos for contributing this image!
题目大意
给定n个非负整数,表示每根杆的宽度为1的高程图,计算雨后它能收集多少水。
例如:给定[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个单位的雨水(蓝色部分)被困住了。
思路
两种思路。
第一种:
两次遍历,空间复杂度为O(1),时间复杂度为O(2n)。
先进行一次遍历,找到数组中的最大值(不是最大值的下标)maxhigh,然后分别进行从两边到maxhigh这个值的位置的遍历,以左边为例,因为已经找到了最大值,从左边第一个值记为left开始向右边进行遍历,当右边的值比左边的值小时,说明形成高度差,该高度差可以截留雨水,如果left右边的值A[i]大于left,就更新left值,将A[i]记为left。
第二种:
只需遍历一遍的解决方案,空间复杂度O(1),时间复杂度为O(n)。
从数组两边向中间找,两边维护两个最大值,每次选较小的那个最大值,然后进行比较,看是否可以截留住雨水。
具体代码如下所示。
代码解析 见 代码解析。
代码
#include<iostream>
using namespace std;
int trap(int A[], int n)
{
if(n <= 2)return 0;
int left_max = A[0];
int right_max = A[n-1];
int i = 1, j = n-2;
int sum = 0;
while(i <= j)
{
if(left_max <= right_max)
{
sum += max(0, left_max-A[i]);
left_max = max(left_max, A[i]);
i++;
}
else
{
sum += max(0, right_max-A[j]);
right_max = max(right_max, A[j]);
j--;
}
}
return sum;
}
int main()
{
int A[] = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1};
cout << trap(A, 12) << endl;
return 0;
}
代码解析
首先选择A[0]和A[n-1]作为两边的最大值分别为:left_max和right_max,
然后从下标为1和n-2的位置分别记为A[ i ]和A[ j ]向中间进行遍历,
每次选择左右较小的那个max值(因为这样的话可以保证如果存在高度差则一定可以截留住雨水),
例如,如果left_max比较小,那么就与A[j],进行比较,
如果left_max - A[j]的值为正数,就说明可以截留住雨水,
如果left_max - A[j]的值为负数,说明不能截留住雨水,并且当前left_max值已经不是最大值,就更新left_max = A[j]。
运行结果

- 以上。
版权声明:本文为博主原创文章,转载请注明出处。
个人博客地址:https://yangyuanlin.club
欢迎来踩~~~~
网友评论