码迷,mamicode.com
首页 > 移动开发 > 详细

leetcode_42_Trapping Rain Water

时间:2015-02-10 11:25:23      阅读:329      评论:0      收藏:0      [点我收藏+]

标签:c++   leetcode   stack   two pointer   

麻烦各位朋友帮忙顶一下增加人气,如有错误或疑问请留言纠正,谢谢技术分享


Trapping Rain Water
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.

思路解析:
找到最高的那块木板,假设其下标为maxId。
分别从左侧和右侧向maxId计算。
左侧计算过程中:
循环实现从i=0 ~ i=maxId
(1)如果当前木板A[i]的高度度小于之前遍历的最大高度max,即A[i}<max,所以i位置能存max-A[i]的水量。
(2)如果当前木板A[i]的高度度大于之前遍历的最大高度max,即A[i}>=max,所以i位置不能存水,同时更新max值。
右侧计算过程与左侧相似。


//vs2012测试代码
#include<iostream>

using namespace std;

#define N 12

class Solution {
public:
    int trap(int A[], int n) 
	{
		int water=0;
        int maxId=0;
		for(int i=1; i<n; i++)
		{
			if( A[i]>A[maxId] )
				maxId = i;
		}
		
		int max = A[0];
		for(int i=1; i<maxId; i++)
		{
			if( A[i] >= max )
				max = A[i];
			else
				water += max - A[i];
		}
		
		max = A[n-1];
		for(int i=n-2; i>maxId; i--)
		{
			if( A[i] >= max )
				max = A[i];
			else
				water += max - A[i];
		}
		return water;
    }
};

int main()
{
	int a,A[N];
	for(int i=0; i<N; i++)
	{
		cin>>a;
		A[i]=a;
	}
	Solution lin;
	cout<<lin.trap( A,N )<<endl;

	return 0;
}

//方法一:自测Accepted
//思路解析:
//1、找到最高的那块木板,假设其下标为maxId。
//2、分别从左侧和右侧向maxId计算。
//左侧计算过程中:
//	循环实现从i=0 ~ i=maxId
//	(1)如果当前木板A[i]的高度度小于之前遍历的最大高度max,即A[i}<max,所以i位置能存max-A[i]的水量。
//	(2)如果当前木板A[i]的高度度大于之前遍历的最大高度max,即A[i}>=max,所以i位置不能存水,同时更新max值。
//右侧计算过程与左侧相似。
class Solution {
public:
    int trap(int A[], int n) 
	{
		int water=0;
        int maxId=0;
		for(int i=1; i<n; i++)
		{
			if( A[i]>A[maxId] )
				maxId = i;
		}
		
		int max = A[0];
		for(int i=1; i<maxId; i++)
		{
			if( A[i] >= max )
				max = A[i];
			else
				water += max - A[i];
		}
		
		max = A[n-1];
		for(int i=n-2; i>maxId; i--)
		{
			if( A[i] >= max )
				max = A[i];
			else
				water += max - A[i];
		}
		return water;
    }
};

//方法二: stack
//基本原理就是找到其中一个个小的容器区间。需要两个堆栈和一个合并区间函数配合。第一个堆栈s1的类型为stack<pair<int, int> >,用来保存容器区间;第二个堆栈s2的类型为stack<int>,用来保存边界的位置。思路如下:
//1、如果堆栈s2为空,把当前位置压入堆栈。
//2、如果堆栈s2不为空:
//	2.1、如果栈顶所在位置的值大于当前位置的值,把当前位置压入堆栈。(A[i] < A[s2.top()])
//	2.2、如果前一条不满足,那么当前位置的值一定大于等于栈顶所在位置的值。(A[i] >= A[s2.top()])
//		(1)如果堆栈s2不为空,并更新左边界位置为栈顶元素,如果左边界上的值大于当前位置的值,停止循环,不然弹出栈顶元素并继续比较。
//		(2)将当前位置压入堆栈。
//		(3)把当前元素所在位置压入堆栈。同时左边界和当前元素的位置正好构成一个容器区间,根据木板原理,容积由较小的值决定。如果s1不为空,栈顶元素可以和当前元素合并,弹出栈顶元素与当前区间合并,再继续循环检查栈顶元素,如果堆栈为空或者栈顶元素不能和当前区间合并,将当前元素压入堆栈。
//3、遍历s1并计算容积。
class Solution {
public:
    bool isInRange(pair<int, int> &left, pair<int, int> &right) {
        return (left.first >= right.first) && (left.second <= right.second);
    }
    
    int getVolume(int A[], pair<int, int> range) {
        int left = range.first, right = range.second;
        int volume = min(A[left], A[right]) * (right - left - 1);
        
        for (int i = left + 1; i < right; ++i) {
            volume -= A[i];
        }
        
        return volume;
    }
    
    int trap(int A[], int n) {
        stack<pair<int, int> > ranges;
        stack<int> bars;
        
        for (int i = 0; i < n; ++i) {
            if (bars.empty()) {
                bars.push(i);
            }
            else {
                if (A[i] < A[bars.top()]) {
                    bars.push(i);
                }
                else {
                    int left;
                    pair<int, int> range;
                    
                    while (!bars.empty()) {
                        left = bars.top();
                        if (A[left] > A[i]) {
                            break;
                        }
                        
                        bars.pop();
                    }
                    
                    bars.push(i);
                    range.first = left;
                    range.second = i;
                    
                    while (!ranges.empty()) {
                        if (isInRange(ranges.top(), range)) {
                            ranges.pop();
                        }
                        else {
                            break;
                        }
                    }
                    
                    ranges.push(range);
                }
            }
        }
        
        int volume = 0;
        
        while (!ranges.empty()) {
            volume += getVolume(A, ranges.top());
            ranges.pop();
        }
        
        return volume;
    }
};


leetcode_42_Trapping Rain Water

标签:c++   leetcode   stack   two pointer   

原文地址:http://blog.csdn.net/keyyuanxin/article/details/43699441

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!