所与nはずっと雨雨を取ることができ、次いで1列の幅の高さマップ算出さクリックコラム装置の非負整数を表します。
上記配列[0,1,0,2,1,0,1,3,2,1,2,1]図高度に表される、この場合には、6つのユニットを取ることができ、雨水(青部分)が雨を表します。この図にマルコスの貢献をありがとうございます。
例:
入力:[0,1,0,2,1,0,1,3,2,1,2,1]
出力:6
分析:
溶液1:暴力
各要素の最小左右の最大値であり、いずれか、及び現在値を減算
時間計算量:左右の各要素の最大値のために必要とされる方のO(N ^ 2)
宇宙複雑:O(1)
クラス解決 { パブリック: int型トラップ(ベクトル< INT >&V) { int型 ANS = 0 ; IF(v.size()== 0 ) 戻り 0 ; のための(INT I = 1。 ;私は<v.size() - 。1 ; I ++ ) { int型 leftmax = 0 ; のための(INT J1 = I- 1。 ; J1> = 0 ; j1--)// 要素の左側の最大値である方 { leftmax = MAX(leftmax、V [J1]); } int型 rightmax = 0 ; のための(INT J2 =私は+ 1。 J2 ++; J2 <v.size())// 右の要素の最大値であり、いずれ { rightmax = MAX( rightmax、V [J2]); } int型 X =分(leftmax、rightmax)-v [I]; // 2つの最大値の最小値をとる IF(X> 0)// 可能な記憶 { ANS + = X ; // 要件を満たしプラス } } リターン年; } }
溶液2:動的プログラミング
暴力各々は、最大要素の最小値を見つけるために、その左右の側面を有する
現在の要素のレコードを、我々は2つの最大O(N)の最小左右の缶を
時間複雑:O(N)
スペースの複雑さ:O(N)
クラス解決 { パブリック: int型トラップ(ベクトル< INT >&V) { int型 ANS = 0 ; IF(v.size()== 0 ) 戻り 0 ; int型 N- = v.size(); int型 DP [N-]。// DP [i]は:最大の現在の最小値は、左及び要素の右側iが DP [ 0 ] = 0 ; DP N- [ - 1 ] = 0 ; のため(int型 = I 1、I <N-は1。; I ++)// 最大値の左 { DP [I] = MAX(DP [I- 1 ]、V [I- 1 ]); } のための(INT I = N- 2 ; I> = 1 ; i--)// 右及び電流最大値最小値比較の左 { DP [I] =分(DP [I]、MAX(DP [Iは、+ 1。 ]、Vは、[I + 1。])); } のための(int型私は= 1 ; Iは< N- 1 ; I ++)// コンプライアンスを蓄積することができる { IF(DP [I] -v [I]> 0 ) ANS + = DP [I] - V [i]は、 } 戻りANS。 } }
解決策3:ダブルポインタ方式について
最初の配列は、右半分と左半分に分割されているK、最高点kを見つけます。
それの左半分の現在の値:
現在の値は、左の最大電流値よりも大きい場合には、水が左に流れ去るだろうが、現在の値は左のみ、最大の外観を更新することができ、水に格納されていない
現在の値が現在よりも大きくない場合左側のマックスは、その後、水を保存することができ生ける水の量は、現在の最大値マイナス現在の値のままにします
それの右半分の現在の値:
現在の値が右側の最大電流値よりも小さい場合には、水が右に流れ去るだろうが、現在の値が最大値のみの右側の外観を更新することができ、水に格納されていない
現在の値が現在よりも大きくない場合右側の最大値は、その後、水が右に保存することができ、生ける水の量は、現在の最大値マイナス電流の値であり、
、最大値に対する左右の最大値は、全左部又は右の部分ではないことに注意してください
左が現在の要素があるの左側にあるすべての要素の最大値に対応する
右辺の最大値は、すべての右側に現在の要素に対応ための要素
時間複雑:O(N)
スペースの複雑さ:O(1)
class Solution { public: int trap(vector<int>& v) { int ans=0; int n=v.size(); if(n==0) return 0; int k=0; for(int i=1; i<n; i++) //找到最高点k,k把数组分为左右两部分(都不包含k) { if(v[i]>v[k]) k=i; } int maxleft=0;//左边最大值指针 for(int i=1; i<k; i++) //左半部分 { if(v[maxleft]<v[i])//不能储水,水向左边流走了 maxleft=i;//更新左边最大值 else ans+=(v[maxleft]-v[i]);//可以储存水 } int maxright=n-1;//右边最大值指针 for(int i=n-2; i>k; i--) //右半部分 { IF(V [maxright <V [I])// 水を保存しません。水が右に離れて流れる maxright = I; // の右辺の最大値更新 他の ANS + =(V [maxright] -v [I]を); //は水を保存することができる } 戻りANSを; } }