麻烦各位朋友帮忙顶一下增加人气,如有错误或疑问请留言纠正,谢谢
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; } };
时间: 2024-10-08 16:24:54