接雨水
阿新 • • 發佈:2020-12-10
技術標籤:刷題資料結構演算法leetcodepython動態規劃
接雨水
給定 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
方法一:依次計算當前位置能接住的雨水
當前位置能接住的雨水等於min(左邊最高的柱子,右邊最高的柱子)- 當前位置的高度
可以先從後向前遍歷一次陣列,記錄當前位置右邊最高的柱子
左邊最高的柱子可以在計算過程中更新
public int trap(int[] height) { if(height.length == 0) return 0; int ans = 0; int leftMax = height[0]; int[] rightMax = new int[height.length]; for (int i = height.length - 2; i >= 0; i--) { rightMax[i] = Math.max(rightMax[i + 1], height[i + 1]); } for (int i = 1; i < height.length - 1; i++) { int h = Math.min(leftMax, rightMax[i]); if (h > height[i]) { ans += h - height[i]; } leftMax = Math.max(leftMax, height[i]); } return ans; }
時間複雜度O(n)
空間複雜度O(n)
方法二:雙指標
在方法一的基礎上,不需要用陣列來存右邊最大高度,只需要用一個變數
- 如果左邊最大高度小於右邊,說明最小的高度由左邊決定
- 如果左邊最大高度小於右邊,說明最小的高度由右邊決定
public int trap(int[] height) { if (height.length == 0) return 0; int ans = 0; int leftMax = height[0]; int rightMax = height[height.length - 1]; int low = 1; int high = height.length - 2; while (low <= high) { while (low <= high && leftMax <= rightMax) { if (leftMax > height[low]) { ans += leftMax - height[low]; } leftMax = Math.max(leftMax, height[low]); low++; } while (low <= high && leftMax > rightMax) { if (rightMax > height[high]) { ans += rightMax - height[high]; } rightMax = Math.max(rightMax, height[high]); high--; } } return ans; }
時間複雜度O(n)
空間複雜度O(1)
方法三:單調遞減棧
用棧來跟蹤可能儲水的最長的條形塊,在遍歷陣列時維護一個棧,如果當前的條形塊小於或等於棧頂的條形塊,我們將條形塊的索引入棧,意思是當前的條形塊被棧中的前一個條形塊界定。如果我們發現一個條形塊高於棧頂,我們可以確定棧頂的條形塊被當前條形塊和棧的前一個條形塊界定,因此我們可以彈出棧頂元素並且累加答案
public int trap(int[] height) {
int ans = 0;
Stack<Integer> stack = new Stack<>();//存下標
for (int i = 0; i < height.length; i++) {
while (!stack.isEmpty() && height[stack.peek()] < height[i]){
int low = height[stack.pop()];//低窪
if (stack.isEmpty()) {
break;
}
int boundHeight = Math.min(height[stack.peek()], height[i]);
int distance = i - stack.peek() - 1;//寬度
ans += (boundHeight - low) * distance;
}
stack.push(i);
}
return ans;
}
時間複雜度O(n)
空間複雜度O(n)