#Leetcode#Q42.接雨水 C++
阿新 • • 發佈:2021-02-11
Solution1: 棧
從左向右遍歷,維護一個從棧底向棧頂遞減的棧,遇到比棧頂小的入棧,遇到大的則出棧
寫的很垃圾,AC 了之後就不想改了
//棧:解法1 class Solution { public: int trap(vector<int>& height) { int res = 0; stack<pair<int,int> > ht; ht.push(pair<int,int>(0,-1)); for(int i=0;i<height.size();++i){ if(height[i] < (ht.top().first)) ht.push(pair<int,int>(height[i],i)); else{ while(ht.size()>1 && height[i] >= ht.top().first){ int bottom = ht.top().first; if(height[i] == ht.top().first){ ht.pop(); break; } ht.pop(); if(ht.top().second < 0) break; int width = i - ht.top().second -1; res += (min(ht.top().first,height[i]) - bottom) * width; } if(height[i] < ht.top().first || (ht.size() == 1 && height[i])) ht.push(pair<int,int>(height[i],i)); } } return res; } };
Solution 2:動態規劃
維護兩個陣列表示左側最高和右側最高,根據木桶理論,只有當前所處位置的高度都低於左右兩側最高的才有可能蓄水,
蓄水量=左右兩側最高中較小的高度-當前高度
class Solution { public: int trap(vector<int>& height) { int len = height.size(); if(len<3) return 0; int res = 0; vector<int> maxleft(len,0); vector<int> maxright(len,0); for(int i=1;i<len;++i) maxleft[i] = max(maxleft[i-1],height[i-1]); for(int i=len-2;i>=0;i--) maxright[i] = max(maxright[i+1],height[i+1]); for(int i=1;i<len-1;++i){ int minvalue = min(maxleft[i],maxright[i]); if(height[i] < minvalue) res += minvalue - height[i]; } return res; } };
Solution 3:動態規劃進階版本
class Solution { public: int trap(vector<int>& height) { int len = height.size(); if(len<3) return 0; //兩個指標分別指向最左側和最右側,只有中間的比兩邊低才有可能蓄水 int res = 0; int left = 1; int right = len-2; int maxleft = height[0]; int maxright = height[len-1]; //i只用作計數,不作為指標 for(int i=1;i<len-1;++i){ //兩個選更矮的那一個方向開始更新。我們需要選出左右兩側最高的矮的一方;如果左側鄰近那個小於右側鄰近那個, if(height[left-1] < height[right+1]){ maxleft = max(maxleft,height[left-1]); if(maxleft > height[left]) res += maxleft - height[left]; left++; }else{ maxright = max(maxright,height[right+1]); if(maxright > height[right]) res += maxright - height[right]; right--; } } return res; } };