《夏洛克福爾摩斯第一章》圖文攻略 全解謎圖文流程攻略
阿新 • • 發佈:2021-11-21
給定 n 個非負整數表示每個寬度為 1 的柱子的高度圖,計算按此排列的柱子,下雨之後能接多少雨水。
示例 1:
- 輸入:height = [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了,我們再把每一列的雨水的高度求出來就可以了。
可以看出每一列雨水的高度,取決於,該列 左側最高的柱子和右側最高的柱子中最矮的那個柱子的高度
即: min(lHeight, rHeight) - height
class Solution { public int trap(int[] height) { return process(height); } private int process(int[] height){ //按列計算 //i:left Max. rightMax. h= min(leftMax,rightMax)-heigt[i]>0 sum+=h if(height.length<=2){ return 0; } int sum=0; for(int i=1;i<height.length-1;i++){ int leftMax=getRangeMax(height,0,i); int rightMax=getRangeMax(height,i,height.length-1); int h=Math.min(leftMax,rightMax)-height[i]; if(h>0){ sum+=h; } } return sum; } private int getRangeMax(int[] height,int L,int R){ int max=0; for(int i=L;i<=R;i++){ max=Math.max(max,height[i]); } return max; } }
動態規劃解法
為了得到兩邊的最高高度,使用了雙指標來遍歷,每到一個柱子都向兩邊遍歷一遍,這其實是有重複計算的。
我們把每一個位置的左邊最高高度記錄在一個數組上(maxLeft),右邊最高高度記錄在一個數組上(maxRight)。這樣就避免了重複計算,這就用到了動態規劃。
當前位置,左邊的最高高度是前一個位置的左邊最高高度和本高度的最大值。
即從左向右遍歷:maxLeft[i] = max(height[i], maxLeft[i - 1]);
從右向左遍歷:maxRight[i] = max(height[i], maxRight[i + 1]);
這樣就找到遞推公式。
class Solution { public int trap(int[] height) { return process(height); } private int process(int[] height){ //leftMax[i] 0....i 求得每個位置左邊的最大值 leftMax[i]=Math.max(dp[i-1],height[i]) //rightMax[i] i....R 求得每個位置右邊的最大值 rightMax[i]=Maht.max(dp[i+1],heigth[i]) //遍歷1....i-1. Math.min(leftMax(i),rightMax(i))-heigt[i] //h >0 sum+=h int n=height.length; if(n<=2){ return 0; } int[] leftMax=new int[n]; leftMax[0]=height[0]; for(int i=1;i<n;i++){ leftMax[i]=Math.max(leftMax[i-1],height[i]); } int[] rightMax=new int[n]; rightMax[n-1]=height[n-1]; for(int i=n-2;i>=0;i--){ rightMax[i]=Math.max(rightMax[i+1],height[i]); } int sum=0; for(int i=1;i<n-1;i++){ int h=Math.min(leftMax[i],rightMax[i])-height[i]; if(h>0) sum+=h; } return sum; } }