参考链接
http://blog.youkuaiyun.com/doc_sgl/article/details/12307171
http://blog.youkuaiyun.com/wzy_1988/article/details/17752809
类似题目
题目描述
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]
, return 6
.
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!
题目分析
对某个值A[i]来说,能trapped的最多的water取决于在i之前最高的值leftMostHeight[i]和在i右边的最高的值rightMostHeight[i](均不包含自身)。
如果min(left,right) > A[i],那么在i这个位置上能trapped的water就是min(left,right) – A[i]。
有了这个想法就好办了,第一遍从左到右计算数组leftMostHeight,第二遍从右到左计算rightMostHeight。
时间复杂度是O(n)。
对于每个A[i]能trapped water的容量,取决于A[i]左右两边的高度(可延展)较小值与A[i]的差值,即volume[i] = [min(left[i], right[i]) - A[i]] * 1,这里的1是宽度,如果the width of each bar is 2,那就要乘以2了总结
代码示例
#include <iostream>
#include <vector>
using namespace std;
#if 0
class Solution {
public:
int trap(int A[], int n) {
int leftIndex = 0, rightIndex = n-1;
int sumWater = 0;
while(!A[leftIndex] && leftIndex<n)leftIndex++; //找到左侧第一个非0
if(leftIndex == n) return 0; //全部为0 返回0
while(!A[rightIndex])rightIndex--; //打到右边第一个非0
if(leftIndex == rightIndex || rightIndex == leftIndex+1)
return 0;//如果左右非0是同一个地方,或者相差一个位置,那个返回0
int maxLIndex = leftIndex, MaxRIndex = rightIndex;
sumWater = 0;
int tmpWater = 0;
//printf("sumWater = %d\n",sumWater);
//从左向右遍历一遍。
for(int i = leftIndex+1;i<=rightIndex;i++)
{
if(A[i] >= A[maxLIndex])//如果当前值超过之前记录的最大值,那个做一个总结
{ // sumWater += (A[maxLIndex]*(i-maxLIndex-1) - tmpWater);
sumWater += (A[maxLIndex]*(i-maxLIndex-1) - tmpWater);
maxLIndex = i;
tmpWater = 0;
//printf("%d:sumWater = %d\n",i,sumWater);
}
else
{
tmpWater += A[i];//这里的A[i]肯定小于 A[maxLIndex],所以A[i]代表的地方不能装水,后面需要减去
//printf("%d:tmpWater = %d\n",i,tmpWater);
}
}
//同理需要从后再向左遍历一遍
tmpWater = 0;
for(int i = rightIndex-1;i>=maxLIndex;i--)
{
if(A[i] >= A[MaxRIndex])
{
sumWater += (A[MaxRIndex]*(MaxRIndex-i-1) - tmpWater);
MaxRIndex = i;
tmpWater = 0;
//printf("%d:sumWater = %d\n",i,sumWater);
}
else
{
tmpWater += A[i];
//printf("%d:tmpWater = %d\n",i,tmpWater);
}
}
return sumWater;
}
};
#elif 1
class Solution {
public:
int trap(int A[], int n) {
// Note: The Solution object is instantiated only once.
if(A==NULL || n<1)return 0;
int maxheight = 0;
vector<int> leftMostHeight(n);
for(int i =0; i<n;i++)
{
leftMostHeight[i]=maxheight;
maxheight = maxheight > A[i] ? maxheight : A[i];
}
maxheight = 0;
vector<int> rightMostHeight(n);
for(int i =n-1;i>=0;i--)
{
rightMostHeight[i] = maxheight;
maxheight = maxheight > A[i] ? maxheight : A[i];
}
int water = 0;
for(int i =0; i < n; i++)
{
int high = min(leftMostHeight[i],rightMostHeight[i])-A[i];
if(high>0)
water += high;
}
return water;
}
};
#endif
void test0()
{
int A[] = {0,1,0,2,1,0,1,3,2,1,2,1};
Solution so;
if(so.trap(A,12) != 6)
printf("------------------------failed\n");
else
printf("------------------------passed\n");
}
void test1()
{
int A[] = {2,0,2};
Solution so;
if(so.trap(A,3) != 2)
printf("------------------------failed\n");
else
printf("------------------------passed\n");
}
int main(int argc, char *argv[])
{
test0();
test1();
return 0;
}