Leetcode: 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.


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!

方法1:模拟


array [0,1,0,2,1,0,1,3,2,1,2,1]的矩阵如上图所示,是一个3*12的矩阵,然后从矩阵的第一行开始扫描,遇到两个1就加上这两个1之间的水量,只要扫描一遍矩阵就得到水量了,代码如下,小集合通过,大集合memory不够用。

Judge Small: Accepted!

Judge Large: Memory Limit Exceeded

int trap(int A[], int n) {
        // Note: The Solution object is instantiated only once.
        if(A==NULL || n<1)return 0;
    	int highest = A[0];
		for(int i=1;i<n;i++)
			if(A[i]>highest)highest=A[i];
		int ** matrix = new int*[highest];
		for(int i=0;i<highest;i++)
		{
			matrix[i]=new int[n];
			memset(matrix[i],0,sizeof(int)*n);
		}
		for(int i = 0; i < n; i++)
			for(int j = 1; j <= A[i]; j++)
				matrix[highest-j][i]=1;
		
		int water = 0;
		int left = -1;
		for(int i = 0; i < highest; i++)
		{
			left = -1;
			for(int j = 0; j < n; j++)
			{
				if(matrix[i][j]==1)
				{
					if(left==-1)
						left = j;
					else
					{
						water += j-left-1;
						left = j;
					}
				}
			}
		}

		for(int i=0;i<highest;i++)
			delete[] matrix[i];
		delete[] matrix;
		return water;
    }


既然memory不够,就把int矩阵改成bool吧,这样空间就由int的4byte缩小到bool的1 byte,但是还是Memory Limit Exceeded

int trap(int A[], int n) {
        // Note: The Solution object is instantiated only once.
        if(A==NULL || n<1)return 0;
    	int highest = A[0];
		for(int i=1;i<n;i++)
			if(A[i]>highest)highest=A[i];
		bool ** matrix = new bool*[highest];
		for(int i=0;i<highest;i++)
		{
			matrix[i]=new bool[n];
			memset(matrix[i],0,sizeof(bool)*n);
		}
		for(int i = 0; i < n; i++)
			for(int j = 1; j <= A[i]; j++)
				matrix[highest-j][i]=1;
		
		int water = 0;
		int left = -1;
		for(int i = 0; i < highest; i++)
		{
			left = -1;
			for(int j = 0; j < n; j++)
			{
				if(matrix[i][j])
				{
					if(left==-1)
						left = j;
					else
					{
						water += j-left-1;
						left = j;
					}
				}
			}
		}

		for(int i=0;i<highest;i++)
			delete[] matrix[i];
		delete[] matrix;
		return water;
    }


但仔细想想感觉这道题应该是扫一遍就能得到结果的。。。

对某个值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)。

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;
    }
精简下代码:
class Solution {
public:
    int trap(vector<int>& height) {
        if(height.size() < 2) return 0;
        int sz = height.size();
        vector<int> left(sz, 0);
        vector<int> right(sz, 0);
        for(int i = 1; i < sz; i++){
            left[i] = max(left[i-1], height[i-1]);
            right[sz-i-1] = max(right[sz-i], height[sz-i]);
        }
        int water = 0;
        for(int i = 1; i < sz; i++){
            int minh = min(left[i],right[i]);
            water += minh > height[i] ? minh - height[i] : 0;
        }
        return water;
    }
};






  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值