您的位置:首页 > 移动开发

42. Trapping Rain Water (Array; DP)

2015-10-09 12:02 429 查看
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!

思路:动态规划。第一次存储从开始到i最高的位置,求最高位置a之前的存水量=a与a之前最高位置b之间的水量+b与b之前最高位置c之间的水量...

第二次存储从末尾到i最高的位置,求最高位置a之后的存水量=a与a之前最高位置m之间的水量+m与m之前最高位置n之间的水量...

class Solution {
public:
int trap(int A[], int n) {
if(n<=2) return 0;
int ret = 0;
int start;
int end;
int* highestTillNow = new int
; //状态

highestTillNow[0] = 0;
for(int i = 1; i<n;i++) //第一次扫描,从头向后
{
if(A[i] > A[highestTillNow[i-1]])
{
highestTillNow[i] = i;
}
else highestTillNow[i] = highestTillNow[i-1];
}
end = highestTillNow[n-1]; //最高位置

//求最高位置前的储水量
while(end>1)
{
start = highestTillNow[end-1]; //最高位置前的次高位置
if(A[start]==0) break;
for(int i = start+1; i <= end-1; i++)
{
ret += A[start]-A[i];
}
end = start;
}

//reverse
end = highestTillNow[n-1];
highestTillNow[n-1] = n-1;
for(int i = n-2; i>end; i--) //第二次扫描,从尾向前
{
if(A[i] > A[highestTillNow[i+1]])
{
highestTillNow[i] = i;
}
else highestTillNow[i] = highestTillNow[i+1];
}

while(end < n-2)
{
start = highestTillNow[end+1];
if(A[start]==0) break;
for(int i = start-1; i >= end+1; i--)
{
ret += A[start]-A[i];
}
end = start;
}
return ret;
}
};


改进:用stack代替vector作为状态存储目前位置最高bar的下标

class Solution {
public:
int trap(vector<int>& height) {
stack<int> currentTop;
int leftIndex;
int rightIndex;
int ret=0;

if(height.empty()) return ret;
//first loop from left to right to cal water at the left of the top bar
currentTop.push(0);
for(int i = 1; i < height.size(); i++){
if(height[i] >= height[currentTop.top()]){//Note the case =
currentTop.push(i);
}
}
rightIndex=currentTop.top();
currentTop.pop();
while(!currentTop.empty()){
leftIndex=currentTop.top();
currentTop.pop();
for(int i = leftIndex+1; i < rightIndex; i++){
ret += height[leftIndex]-height[i];
}
rightIndex=leftIndex;
}

//then loop from right to left to cal water at the right of the top bar
currentTop.push(height.size()-1);
for(int i = height.size()-2; i >= 0; i--){
if(height[i] >= height[currentTop.top()]){
currentTop.push(i);
}
}
leftIndex=currentTop.top();
currentTop.pop();
while(!currentTop.empty()){
rightIndex=currentTop.top();
currentTop.pop();
for(int i = leftIndex+1; i < rightIndex; i++){
ret += height[rightIndex]-height[i];
}
leftIndex=rightIndex;
}

return ret;
}
};


Result:

Input:[2,0,2]
Output:4
Expected:2
左右两次loop因为最高高度相同,所以重复计算了!
解决方法:第一次遍历考虑=的情况,第二次不考虑

class Solution {
public:
int trap(vector<int>& height) {
stack<int> currentTop;
int leftIndex;
int rightIndex;
int ret=0;

if(height.empty()) return ret;
//first loop from left to right to cal water at the left of the top bar
currentTop.push(0);
for(int i = 1; i < height.size(); i++){
if(height[i] >= height[currentTop.top()]){//Note the case =
currentTop.push(i);
}
}
rightIndex=currentTop.top();
currentTop.pop();
while(!currentTop.empty()){
leftIndex=currentTop.top();
currentTop.pop();
for(int i = leftIndex+1; i < rightIndex; i++){
ret += height[leftIndex]-height[i];
}
rightIndex=leftIndex;
}

//then loop from right to left to cal water at the right of the top bar
currentTop.push(height.size()-1);
for(int i = height.size()-2; i >= 0; i--){
if(height[i] > height[currentTop.top()]){ //neglect case =
currentTop.push(i);
}
}
leftIndex=currentTop.top();
currentTop.pop();
while(!currentTop.empty()){
rightIndex=currentTop.top();
currentTop.pop();
for(int i = leftIndex+1; i < rightIndex; i++){
ret += height[rightIndex]-height[i];
}
leftIndex=rightIndex;
}

return ret;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: