LeetCode 42. Trapping Rain Water
主要參考思路
全文圍繞一個定理展開:在某個位置
i
i
i 處,它能存的水,取決於它左右兩邊的最大值中較小的一個
JAVA
① 按行求【超時】
class Solution {
public int trap(int[] height) {
int len = height.length;
int max_height = getMax(height); // 獲取最高層數
int ans = 0; // 總儲水量
for (int i = 1; i <= max_height; ++i) {
int temp = 0; // 臨時儲水量
boolean isStart = false;
for (int j = 0; j < len; ++j) {
if (isStart && height[j] < i) {
temp++;
}
if (height[j] >= i) {
ans += temp;
temp = 0;
isStart = true;
}
}
}
return ans;
}
private int getMax(int[] height) {
int len = height.length;
int ans = 0;
for (int i = 0; i < len; ++i) {
ans = Math.max(ans, height[i]);
}
return ans;
}
}
但這種程式碼在下面這種情況下會出錯
實際答案是
1
1
1,但因為陣列最右邊多出了
0
0
0,因此實際輸出會變成
2
2
2
② 按列求(動態規劃)【時間複雜度: O ( N ) O(N) O(N) 空間複雜度: O ( N ) O(N) O(N)】
class Solution {
public int trap(int[] height) {
int len = height.length;
int[] left_max = new int[len]; // 當前位置往左邊牆最大的高度
int[] right_max = new int[len]; // 當前位置往右邊牆最大的高度
for (int i = 1; i <= len - 2; ++i) {
left_max[i] = Math.max(left_max[i - 1], height[i - 1]); // left_max[0]自然是 0
}
for (int i = len - 2; i >= 1; --i) {
right_max[i] = Math.max(right_max[i + 1], height[i + 1]); // right_max[len - 1]自然是 0
}
int ans = 0;
for (int i = 1; i <= len - 2; ++i) {
int temp_min = Math.min(left_max[i], right_max[i]);
if (temp_min > height[i]) {
ans += temp_min - height[i];
}
}
return ans;
}
}
③ 雙指標【時間複雜度: O ( N ) O(N) O(N) 空間複雜度: O ( 1 ) O(1) O(1)】
class Solution {
public int trap(int[] height) {
int ans = 0;
int len = height.length;
int left_max = 0;
int right_max = 0;
int left = 1;
int right = len - 2;
for (int i = 1; i <= len - 2; ++i) {
if (height[left - 1] < height[right + 1]) {
left_max = Math.max(left_max, height[left - 1]);
if (height[left] < left_max) {
ans += left_max - height[left];
}
left++;
} else {
right_max = Math.max(right_max, height[right + 1]);
if (height[right] < right_max) {
ans += right_max - height[right];
}
right--;
}
}
return ans;
}
}
為什麼不一開始判斷時用 left_max < right_max
?
答:因為一開始兩者都等於 0,無法進行判斷,而 height[left - 1]
是可能成為 left_max
的變數, 同理,height [right + 1]
是可能成為 right_max
的變數,只要保證 height[left - 1] < height[right + 1]
,那麼 left_max
就一定小於 right_max
,因此我們可以用 height[left - 1] < height[right + 1]
代替 left_max < right_max
④ 單調棧【時間複雜度: O ( N ) O(N) O(N) 空間複雜度: O ( N ) O(N) O(N)】
import java.util.Deque;
import java.util.LinkedList;
public class Solution {
public int trap(int[] height) {
if (height == null) {
return 0;
}
Deque<Integer> stack = new LinkedList<>();
int ans = 0;
for (int i = 0; i < height.length; i++) {
while(!stack.isEmpty() && height[stack.peek()] < height[i]) {
int curIdx = stack.pop();
// 如果棧頂元素一直相等,那麼全都pop出去,只留第一個。
while (!stack.isEmpty() && height[stack.peek()] == height[curIdx]) {
stack.pop();
}
if (!stack.isEmpty()) {
int stackTop = stack.peek();
// stackTop此時指向的是此次接住的雨水的左邊界的位置。右邊界是當前的柱體,即i。
// Math.min(height[stackTop], height[i]) 是左右柱子高度的min,減去height[curIdx]就是雨水的高度。
// i - stackTop - 1 是雨水的寬度。
ans += (Math.min(height[stackTop], height[i]) - height[curIdx]) * (i - stackTop - 1);
}
}
stack.add(i);
}
return ans;
}
}
單調棧參考文章
雖然但是,我還是看不懂啊!
需要注意的地方是不直接使用 S t a c k Stack Stack,而使用 D e q u e Deque Deque 代替 S t a c k Stack Stack
Python
① 按列求(動態規劃)(48ms)
class Solution:
def trap(self, height: List[int]) -> int:
length=len(height)
ans=0
left_max=[0]*length # 相當於初始化陣列
right_max=[0]*length
for i in range(1,length-1):
left_max[i]=max(height[i-1],left_max[i-1])
for i in range(length-2,0,-1): # 加個 -1表示倒著遍歷
right_max[i]=max(height[i+1],right_max[i+1])
for i in range(1,length-1):
tmp_max=min(left_max[i],right_max[i])
if tmp_max>height[i]:
ans+=tmp_max-height[i]
return ans
② 雙指標(44ms)
class Solution:
def trap(self, height: List[int]) -> int:
length=len(height)
ans=0
left_max,right_max=0,0
left,right=1,length-2
for i in range(1,length-1): # 可以替換成 while left<=right:
if height[left-1]<height[right+1]:
left_max=max(left_max,height[left-1])
if left_max>height[left]:
ans+=left_max-height[left]
left+=1
else:
right_max=max(right_max,height[right+1])
if right_max>height[right]:
ans+=right_max-height[right]
right-=1
return ans
③ 單調棧(44ms)
class Solution:
def trap(self, height: List[int]) -> int:
n = len(height)
if n == 0:
return 0
stack = []
ans = 0
for i in range(n):
while stack and stack[-1][0] < height[i]:
tmp = stack.pop() # 刪除的是最右邊的元素,因此可作為堆使用
while stack and stack[-1][0] == tmp[0]:
stack.pop()
if stack:
ans += (min(stack[-1][0], height[i])-tmp[0])*(i-stack[-1][1]-1)
stack.append([height[i], i])
return ans
本程式碼的
s
t
a
c
k
stack
stack 是二維的,一維代表索引,二維的 stack[i][0]
代表牆高度,stack[-1][1]
代表下標
判斷
s
t
a
c
k
stack
stack 是不是空不需要使用函式,只用 if stack
即可
相關文章
- Leetcode 之 PHP 解析 (42. Trapping Rain Water)LeetCodePHPAPPAI
- Leetcode 42 Trapping Rain WaterLeetCodeAPPAI
- Trapping Rain WaterAPPAI
- Leetcode Trapping Raining waterLeetCodeAPPAI
- Trapping-rain-waterAPPAI
- 每日leetcode——42. 接雨水LeetCode
- LeetCode-Water and Jug ProblemLeetCode
- leetcode Container With Most WaterLeetCodeAI
- [LeetCode] 417. Pacific Atlantic Water FlowLeetCode
- Leetcode 11 Container With Most WaterLeetCodeAI
- Leetcode-Container With Most WaterLeetCodeAI
- Container With Most Water leetcode javaAILeetCodeJava
- leetcode_11. Container With Most WaterLeetCodeAI
- LeetCode 11. Container With Most WaterLeetCodeAI
- LeetCode - Medium - 11. Container With Most WaterLeetCodeAI
- [LeetCode] Container With Most Water 裝最多水的容器LeetCodeAI
- LeetCode Container With Most Water(011)解法總結LeetCodeAI
- C. Mixing Water
- leetcode 417. Pacific Atlantic Water Flow 太平洋大西洋水流問題LeetCode
- 11. Container With Most WaterAI
- 水紋效果(Water)源程式. (轉)
- LeetCode 1326. Minimum Number of Taps to Open to Water a Garden 動態規劃 離散化 貪心LeetCode動態規劃
- constraint=constraints?AI
- LeetCodeHot100 283. 移動零 11. 盛最多水的容器 42. 接雨水 15. 三數之和LeetCode
- 劍指 Offer 42.連續子陣列的最大和陣列
- Kiss the rainAI
- trainAI
- TrainerAI
- Codeforces Round 689(Div.2) E題 Water Level
- Oracle段高水位(HWM, high water mark)問題Oracle
- 沙因的睡蓮模型(Water lily model) (轉載)模型
- Android ConstraintLayout 2.0:ConstraintLayoutStatesAndroidAI
- Bootstrap系列 -- 42. 導航條中的按鈕、文字和連結boot
- 解密prompt系列42. LLM通往動態複雜思維鏈之路解密
- Flutter | ConstrainedBox & UnconstrainedBox 元件FlutterAI元件
- ConstraintAI
- rhythm of the rainAI
- sabsatrainingAI