接雨水问题

#include<iostream>
#include<stack>
#include<vector>
#include<algorithm>

using namespace std;

//接雨水这个问题,通过分析题目意思,我们可以看到
//实际就是找到这样性质的数:这个数不但小于他左边的数,而且小于他右边的数
//只要找到这个数,他两边的数加上他,三个数形成的柱状图就可以形成一个凹槽从而就可以接雨水了

//为了找到这样的数而且方便取得这三个数,我们可以利用栈的特性,
//雨水vec中的元素(下标)依次入栈且维持一单调递增栈(栈内元素从栈顶到栈底是单调递减小的)

//栈顶元素始终时栈内元素的最小值,栈内元素从栈底到栈顶时单调递减小的
//这样的话,下一个元素如果要入栈,先做检查,当比栈顶元素大时,就可以发现
//栈顶元素以及栈顶元素下面的元素和想要进栈的元素,三个棍就可以形成凹槽,接到雨水
//计算这三根棍的凹槽可接的雨水后,栈顶元素出战,再看看这时候栈顶两个元素是否可以和想要入栈的这根棍子
//形成凹槽,可以的话,接着计算凹槽面积
//仍然利用了栈的回溯思想,用即将入栈的这个数据,不断地和栈顶元素看看是否能形成凹槽
//用这个数据回溯单调递增站之前的数据,判断是否能形成凹槽,能形成的话加入总面积

int getArea(vector<int>& hightVector)
{
	if (hightVector.size() < 2)
	{
		return 0;//小于等于两根柱子,没法形成凹槽接到雨水
	}

	//初始的时候面积为0
	int resultArea = 0;

	//维护一个单调递增栈(栈底到栈顶降序,栈顶到栈底升序)
	stack<int> increasStk;

	for (int i = 0; i < hightVector.size(); i++)
	{
		//构建单调递增栈
		if (increasStk.empty())
		{
			//栈内的元素放下标值,因为下标可以一一对应到到highVec的值而且方便之后计算积水宽度
			increasStk.push(i);
		}
		else if (hightVector[increasStk.top()] >= hightVector[i])
		{
			//新元素小于等于栈顶元素,无法形成凹槽,直接入栈,更新了栈的栈顶元素,再次根据此栈顶元素寻找凹槽
			increasStk.push(i);
		}
		else
		{
			//这个时候,在栈顶元素的底部元素存在值的情况下,栈顶元素和栈顶元素下面紧挨的那个元素以及想要入栈的这个新元素
			//可以形成凹槽,我们计算这三个高度值的面积

			//由于栈中可能存在多个元素,移除栈顶元素之后,剩下的元素和此时的元素也有可能形成凹槽
			//因此,我们需要不断比较此时的元素和栈顶元素,
			//此时元素仍然大于栈顶元素时,我们去计算凹槽面积
			//这个思路通过while(栈顶不断变动)去实现(有一次体现了回溯与while通常相互联系)
			//回溯其实就是利用了栈能够记录不断变得更新的阶段性成果或者历史数据或者更最新的解决方案

			while (!increasStk.empty() && hightVector[increasStk.top()] < hightVector[i])
			{
				int bottom = increasStk.top();//如果可以形成凹槽的话,栈顶元素就是凹槽底部的元素的下标

				//栈顶元素出栈,出栈后如果栈不为空,方便看当前元素能否和新的栈顶元素形成凹槽
				increasStk.pop();

				//increasStk.pop();出栈后要看栈内还有没有元素能充当左边的高度,有值的话才能形成凹槽
				if (!increasStk.empty())
				{
					//计算面积
					//[5,3,6]形成的凹槽的底部宽度是6的下标减5的下标再减去1,即2 - 0 - 1 = 1,s = 1 * min(5,6)
					int with = i - increasStk.top() - 1;
					//高度是两边柱子取小值
					int high = min(hightVector[i], hightVector[increasStk.top()]) - hightVector[bottom];

					resultArea += with * high;
				}
				else
				{
					//入栈序列时[1,2,0,3],当分析2的时候,2>1,但是1出栈后没有左边的高度,
					//栈空了,2这个高度无法仅仅与1形成凹槽,此时2应该入栈,看是否能与后面的高度值形成凹槽
					increasStk.push(i);
				}
			}

		}
	}
	return resultArea;
}

int main()
{
	vector<int> hightVector = { 0,1,0,2,1,0,1,3,2,1,2,1 };
	int result = getArea(hightVector);

	cout << result << endl;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值