LC.42.接雨水
方法好多,學習到了。
1.對每個柱子向左向右暴力枚舉最大柱子,然後取較小的作爲貢獻。時間複雜度,會
2.由1可以想到,預處理一下向左,向右的最大值,即預處理前綴最大值,和後綴最大值即可。時間複雜度:
class Solution {
public:
int trap(vector<int>& h) {
if(h.empty()) return 0;
int n=h.size();
vector<int>pre(n,0);
vector<int>suf(n,0);
pre[0]=h[0];
int ans=0;
for(int i=1;i<n;i++)
pre[i]=max(pre[i-1],h[i]);
suf[n-1]=h[n-1];
for(int j=n-2;j>=0;j--)
suf[j]=max(suf[j+1],h[j]);
for(int i=1;i<n-1;i++){
ans+=min(pre[i],suf[i])-h[i];
}
return ans;
}
};
3.用單調遞減棧維護一個前綴,然後枚舉每個可能作爲裝水柱的右端柱子,如果比棧頂矮直接入棧,否則計算貢獻。時間複雜度:。
class Solution {
public:
int trap(vector<int>& h) {
stack<int>s;
int ans=0;
int n=h.size();
for(int i=0;i<n;i++){
while(!s.empty()&&h[s.top()]<=h[i]){
int pos=s.top();
s.pop();
if(s.empty()) break;
int hm=min(h[i],h[s.top()])-h[pos];
ans+=hm*(i-s.top()-1);
}
s.push(i);
}
return ans;
}
};
4.雙指針法,官方解法很妙,這裏不多講了。
class Solution {
public:
int trap(vector<int>& h) {
int l=0,r=h.size()-1;
int lmx=0,rmx=0;
int ans=0;
while(l<=r){
if(h[l]<h[r]){
lmx<=h[l]?lmx=h[l]:ans+=lmx-h[l];
l++;
}
else {
rmx<=h[r]?rmx=h[r]:ans+=rmx-h[r];
r--;
}
}
return ans;
}
};
5.填補法。
向左掃的有效矩形面積+向右掃的矩形面積-柱子的面積-整個矩形的面積就是答案,可以畫圖看下。
class Solution {
public:
int trap(vector<int>& h) {
int s1=0,s2=0,sum=0;
int n=h.size();
int lmx=0,rmx=0;
for(int i=0;i<n;i++){
lmx=max(lmx,h[i]);
rmx=max(rmx,h[n-1-i]);
s1+=lmx,s2+=rmx;
sum+=h[i];
}
return s1+s2-sum-max(lmx,rmx)*n;
}
};