Leetcode题目之"Trapping Rain Water"

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">题目来源:https://leetcode.com/problems/trapping-rain-water/</span>

题目描述:

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.

解题思路:题目意思是说给定一个非负数的一维数组,数组中元素的值表示阶梯的高度,如上图中的黑色部分,阶梯的宽度都是1,问最多可以存储多少雨水?

容易想到的是高的阶梯之间可以存储较多的雨水,所以解题的第一步就是找出峰值阶梯,即给定的数组中的峰值,同时满足height[i]>=height[i-1]和height[i]>=height[i+1]的即为峰值,头尾两个阶梯只要满足大于相邻的一个阶梯即可。找出的峰值存于数组posI中。(如下面程序所示)

第二步是找出posI中的两个最大值,分别存于变量maxPos1和maxPos2中,从而将整个数组分为三个部分,两个最大值中间的部分,左边的部分和右边的部分。

第三步是找出用于计算雨水量的关键阶梯,如下面程序所示。

程序代码:

int trap(vector<int>& height){

	vector<int> posI;
	vector<int> posIICenter;
	vector<int> posIILeft;
	vector<int> posIIRight;
	int waterSum = 0, sum = 0, lowWidth = 0,waterSumLeft=0,waterSumRight=0,waterSumCenter=0;
	int count = 0, maxPos1 = 0,maxPos2=0,maxLeftTemp=0,maxRightTemp=0,lastLeft=0,lastRight=0;
	bool leftFlag = false, rightFlag = false;

	//construct posI
	if (height.size()<2) return 0;

	if (height[0]>height[1]) {
		posI.push_back(0);
	}
	for (int i = 1; i < height.size() - 1; i++){
		if (height[i] >= height[i - 1] && height[i] >= height[i + 1]){
			posI.push_back(i);
		}
	}
	if (height[height.size() - 1]>height[height.size() - 2]) {
		posI.push_back(height.size() - 1);
	}

	//construct posII=posIILegt+posIICenter+posIIRight
	if (posI.size() < 2) return 0;
	for (int i = 1; i < posI.size(); i++){// find max peak
		if (height[posI[i]]>=height[posI[maxPos1]]){
			maxPos1 = i;
		}
	}
	if (maxPos1==0){
		maxPos2 = 1;
		for (int i = 2; i <posI.size();i++){
			if (height[posI[i]]>=height[posI[maxPos2]]){
				maxPos2 = i;
			}
		}
	}
	else{
		for (int i = 1; i < posI.size(); i++){//find second max peak
			if (height[posI[i]] >= height[posI[maxPos2]] && i != maxPos1){
				maxPos2 = i;
			}
		}
	}
	if (maxPos1 > maxPos2){
		int temp = maxPos1;
		maxPos1 = maxPos2;
		maxPos2 = temp;
	}
	posIICenter.push_back(posI[maxPos1]);
	posIICenter.push_back(posI[maxPos2]);

	if (maxPos1 > 0){
		posIILeft.push_back(posI[maxPos1]);
		for (int i = 0; i < maxPos1; i++){
			if (height[posI[i]] >= height[posI[maxLeftTemp]]){
				maxLeftTemp = i;
			}
		}
		posIILeft.push_back(posI[maxLeftTemp]);
		if (maxLeftTemp == 0){
			leftFlag = true;
		}

		while (!leftFlag){
			lastLeft = maxLeftTemp;
			maxLeftTemp = lastLeft-1;
			for (int i = lastLeft-2; i > -1; i--){
				if (height[posI[i]] >= height[posI[maxLeftTemp]]){
					maxLeftTemp = i;
				}
			}
			if (maxLeftTemp == 0){
				leftFlag = true;
			}
			posIILeft.push_back(posI[maxLeftTemp]);
		}
		
	}//maxPos1>0

	if (maxPos2 < posI.size()-1){
		posIIRight.push_back(posI[maxPos2]);
		maxRightTemp = posI.size() - 1;
		for (int i = posI.size() - 2; i>maxPos2; i--){
			if (height[posI[i]] > height[posI[maxRightTemp]]){
				maxRightTemp = i;
			}
		}
		posIIRight.push_back(posI[maxRightTemp]);
		if (maxRightTemp == posI.size() - 1){
			rightFlag = true;
		}
		
		while (!rightFlag){
			lastRight = maxRightTemp;
			maxRightTemp = lastRight + 1;
			for (int i = lastRight+2; i < posI.size(); i++){
				if (height[posI[i]] >= height[posI[maxRightTemp]]){
					maxRightTemp = i;
				}
			}
			posIIRight.push_back(posI[maxRightTemp]);
			if (maxRightTemp == posI.size() - 1){
				rightFlag = true;
			}
		}
	}//maxPos2 < posI.size()-1

	//caculate rainwater
	// waterSum=waterSumLeft+waterSumCenter+waterSumRight
	if (height[posI[maxPos1]] >= height[posI[maxPos2]]){
		for (int i = posI[maxPos1] + 1; i < posI[maxPos2]; i++){
			if (height[i] < height[posI[maxPos2]]){
				sum = sum + height[i];
				lowWidth = lowWidth + 1;
			}
		}
		waterSumCenter = height[posI[maxPos2]] * lowWidth - sum;
	}
	else{
		for (int i = posI[maxPos1] + 1; i < posI[maxPos2]; i++){
			if (height[i] < height[posI[maxPos1]]){
				sum = sum + height[i];
				lowWidth = lowWidth + 1;
			}
		}
		waterSumCenter = height[posI[maxPos1]] * lowWidth - sum;
	}
	sum = 0;
	lowWidth = 0;
	
	if (posIILeft.size() > 1){
		for (int i = 0; i<posIILeft.size() - 1; i++){
			sum = 0;
			lowWidth = 0;
			for (int j = posIILeft[i+1] + 1; j<posIILeft[i]; j++){
				if (height[j] < height[posIILeft[i + 1]]){
					sum = sum + height[j];
					lowWidth = lowWidth + 1;
				}
			}
			waterSumLeft = waterSumLeft + height[posIILeft[i + 1]] * lowWidth - sum;
		}
	}
	sum = 0;
	lowWidth = 0;

	if (posIIRight.size() > 1){
		for (int i = 0; i<posIIRight.size() - 1; i++){
			sum = 0;
			lowWidth = 0;
			for (int j = posIIRight[i] + 1; j < posIIRight[i + 1]; j++){
				if (height[j] < height[posIIRight[i + 1]]){
					sum = sum + height[j];
					lowWidth = lowWidth + 1;
				}
			}
			waterSumRight = waterSumRight + height[posIIRight[i+1]] * lowWidth - sum;
		}
	}

	waterSum = waterSumLeft + waterSumCenter + waterSumRight;
	return waterSum;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值