标签: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