LeetCode 42. Trapping Rain Water
首先说说最初的但是不正确的思路,stk存值,初始化为输入数组的第一位。从左往右读入数组每一位,如果height[i]>stk.top(),说明stk.top()无法蓄水,pop掉,替换为height[i];如果height[i]<=stk.top(),那么从i开始遍历,直到找到大于等于stk.top()的height[i]或者直到最后一位,找的时候维护变量tmp存蓄水的量,但是如果没有找到大于等于stk.top()的height[i]的话,实际上是无法蓄水的,也就是tmp是无意义的(因此要另开变量tmp而不是直接加给res),这种情况下stk要pop,然后push进原top值的下一个高度,所以还要开一个变量top_pos,存放stk.top()在数组中的位置;如果能够找到大于等于stk.top()的height[i]的话,res+=tmp,stk要pop,push进当前大于等于stk.top()的height[i]。
其实不用开stack,stk应该全程只有一个数据,因为看到tag是stack所以开了一个,实际上int变量即可。
1 class Solution { 2 public: 3 int trap(vector<int>& height) { 4 int size = height.size(); 5 if(size == 0) return 0; 6 int i = 0, top_pos = 0; 7 int res = 0; 8 stack<int> stk; 9 stk.push(height[i++]); 10 for(; i < size; ++i){ 11 if(height[i] > stk.top()){ 12 stk.pop(); 13 stk.push(height[i]); 14 top_pos = i; 15 } 16 else{ 17 int tmp = 0; 18 while(i <= size - 1 && height[i] < stk.top()){ 19 tmp += stk.top() - height[i]; 20 ++i; 21 } 22 if(i == size) i = size - 1; 23 if(height[i] < stk.top()){ 24 stk.pop(); 25 i = ++top_pos; 26 stk.push(height[i]); 27 } 28 else{ 29 res += tmp; 30 stk.pop(); 31 stk.push(height[i]); 32 top_pos = i; 33 } 34 } 35 } 36 return res; 37 } 38 };
这种算法140/315 test cases passed.
1 class Solution { 2 public: 3 int trap(vector<int>& height) { 4 int sz=height.size(), highest=0, water=0; 5 //from left to right, only consider the trap's left elevation 6 for(int i=0; i<sz; i++){ 7 if(height[i]<highest) water+=highest-height[i]; 8 highest=max(highest, height[i]); 9 } 10 11 int prehighest=highest; 12 highest=0; 13 //from right to left, only consider the trap's right elevation, subtract the surplus water 14 for(int i=sz-1; i>=0; i--){ 15 highest=max(height[i], highest); 16 if(highest<prehighest) water-=prehighest-highest; 17 } 18 return water; 19 } 20 };
以下是用deque的算法,两头进出,其实也可转换为stack,思路相同。
注意能够蓄水的条件是有凹陷,也就是一端的高度大于等于另一端高度,两端之间的高度小于它们两者,也即栈底为某一高度,当之后的高度都比它小时,就push进去,如果大于等于它,就可以形成凹陷,一直pop,计算水量。
注意可能出现一个高度之后的高度都小于它的情况,但是仍可能存在凹陷,因此将高度全部读入后还要检测deque是否为空,不为空的话就表明这种情况发生了,解决方法很简单,把deque里的数据pop_back进另一个deque,这样一来最高的高度变成了最末尾的一个,就可以形成常规凹陷,和之前判断凹陷的方法一样。这种操作执行一次即可。
1 class Solution { 2 public: 3 int trap(vector<int>& height) { 4 int n = height.size(); 5 // cin>>n; 6 // int * height = new int[n + 10]; 7 deque<int> q; 8 int water = 0; 9 int maxH = 0; 10 for(int i = 0; i < n; ++i){ 11 int cur = height[i]; 12 13 if(q.empty()) {q.push_back(cur);maxH = cur;} 14 else{ 15 if(cur < maxH) q.push_back(cur); 16 else if(cur >= maxH){ 17 while(!q.empty()){ 18 water += maxH - q.back(); 19 q.pop_back(); 20 } 21 maxH = cur; 22 q.push_back(cur); 23 } 24 else continue; 25 } 26 27 28 } 29 if(!q.empty()){ 30 deque<int> tmp; 31 while(!q.empty()){ 32 int cur = q.back(); 33 if(tmp.empty()) {tmp.push_back(cur); maxH = cur;} 34 else{ 35 if(cur < maxH) tmp.push_back(cur); 36 else if(cur >= maxH){ 37 while(!tmp.empty()){ 38 water += maxH - tmp.back(); 39 tmp.pop_back(); 40 } 41 maxH = cur; 42 tmp.push_back(cur); 43 } 44 } 45 q.pop_back(); 46 } 47 } 48 return water; 49 } 50 };