標籤: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 12class 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];elsewater += max - A[i];}max = A[n-1];for(int i=n-2; i>maxId; i--){if( A[i] >= max )max = A[i];elsewater += 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];elsewater += max - A[i];}max = A[n-1];for(int i=n-2; i>maxId; i--){if( A[i] >= max )max = A[i];elsewater += 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