這題難度還是在想到辦法,實現並不困難
如何計算雨水呢,可以按列來算,統計每列能接的雨水
列的寬度已經確定了,能接雨水的高度等於
min(左側最高的高度,右側最高的高度)-本列高度
首先介紹雙指針,左側右側靠掃描來計算
class Solution { public int trap(int[] height) { int result=0; for(int i=0;i<height.length;i++) { if(i==0||i==height.length-1) {continue;} int heightLeft=height[i],heightRight=height[i]; for(int left=i;left>=0;left--) { if(height[left]>heightLeft) { heightLeft=height[left]; } } for(int right=i;right<height.length;right++) { if(height[right]>heightRight) { heightRight=height[right]; } } int h=Math.min(heightLeft,heightRight)-height[i]; if(h>0) {result+=h;} } return result; } }
由於第一列和最後一列肯定接不到雨水,所以直接爲0
這樣的時間複雜度是On2
還可以用動態規劃來尋找左側右側,遞推方程如下:
這裏需要注意邊緣情況的maxLeft,要記住一個列的最小maxLeft就是height[i],這樣意味着它是最高的,所以存不了水
class Solution { public int trap(int[] height) { int result=0; int[] maxLeft=new int[height.length]; int[] maxRight=new int[height.length]; for(int i=0;i<height.length;i++) { if(i==0) {maxLeft[i]=height[0];} else { maxLeft[i]=Math.max(height[i],maxLeft[i-1]); } } for(int i=height.length-1;i>=0;i--) { if(i==height.length-1) {maxRight[i]=height[i];} else { maxRight[i]=Math.max(height[i],maxRight[i+1]); } } for(int i=0;i<height.length;i++) { int h=Math.min(maxLeft[i],maxRight[i])-height[i]; if(h>0) {result+=h;} } return result; } }
本題還有一種解法叫單調幀法,可以在O1的空間複雜度和On的複雜度完成這道題