LeetCode 0042
About 4 min
0042. Trapping Rain Water
- Nhãn: Stack, Mảng, Con trỏ kép, Quy hoạch động, Stack đơn điệu
- Độ khó: Khó
Tóm tắt đề bài
Mô tả: Cho n
số nguyên không âm biểu thị đồ thị chiều cao của n
cột có chiều rộng 1
, được biểu diễn bằng mảng height
, trong đó height[i]
biểu thị chiều cao của cột thứ i
.
Yêu cầu: Tính toán số lượng nước mà đồ thị có thể nhận được sau khi mưa.
Giải thích:
- .
- .
- .
Ví dụ:
- Ví dụ 1:
Input: height = [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
Explanation: Trên là đồ thị chiều cao được biểu diễn bằng mảng [0,1,0,2,1,0,1,3,2,1,2,1]. Trong trường hợp này, có thể nhận được 6 đơn vị nước (phần màu xanh biểu thị nước mưa).
- Ví dụ 2:
Input: height = [4,2,0,3,2,5]
Output: 9
Ý tưởng
Ý tưởng 1: Stack đơn điệu
- Duyệt qua mảng chiều cao
height
. - Nếu chiều cao cột hiện tại nhỏ hơn hoặc bằng chiều cao cột đỉnh của stack, thì đẩy chiều cao cột hiện tại vào stack.
- Nếu chiều cao cột hiện tại lớn hơn chiều cao cột đỉnh của stack, tiếp tục đẩy cột đỉnh của stack ra khỏi stack cho đến khi chiều cao cột hiện tại nhỏ hơn hoặc bằng chiều cao cột đỉnh của stack.
- Giả sử cột hiện tại là
C
, cột bị đẩy ra khỏi stack làB
, cột đỉnh mới của stack làA
. Khi đó:- Cột hiện tại
C
là cột đầu tiên mà cột bị đẩy ra khỏi stackB
tìm thấy từ bên phải có chiều cao lớn hơn cột hiện tại. Vì vậy, có thể mở rộng chiều rộng từ cột bị đẩy ra khỏi stackB
sang phải đến cột hiện tạiC
. - Cột đỉnh mới của stack
A
là cột đầu tiên mà cột bị đẩy ra khỏi stackB
tìm thấy từ bên trái có chiều cao lớn hơn cột hiện tại. Vì vậy, có thể mở rộng chiều rộng từ cột bị đẩy ra khỏi stackB
sang trái đến cột đỉnh mới của stackA
.
- Cột hiện tại
- Sau khi đẩy ra khỏi stack, sử dụng cột đỉnh mới của stack
A
làm biên trái, sử dụng cột hiện tạiC
làm biên phải, sử dụng hiệu chênh lệch chiều cao giữa biên trái và biên phải với chiều cao cột bị đẩy ra khỏi stackB
làm chiều cao, tính toán diện tích có thể nhận được nước. Sau đó, ghi lại và cập nhật diện tích tích lũy.
Ý tưởng 1: Code
class Solution:
def trap(self, height: List[int]) -> int:
ans = 0
stack = []
size = len(height)
for i in range(size):
while stack and height[i] > height[stack[-1]]:
cur = stack.pop(-1)
if stack:
left = stack[-1] + 1
right = i - 1
high = min(height[i], height[stack[-1]]) - height[cur]
ans += high * (right - left + 1)
else:
break
stack.append(i)
return ans
Ý tưởng 1: Độ phức tạp
- Độ phức tạp thời gian: , trong đó là độ dài của mảng
height
. - Độ phức tạp không gian: .
Ý tưởng 2: Con trỏ kép
Từ hình ảnh ví dụ, ta có thể thấy rằng với cột i
, nếu có 1 cột bên trái l
và 1 cột bên phải r
cao hơn thì chắc chắn cột i
sẽ bị chìm trong nước. Lượng nước ngập trên cột i
sẽ là từ độ cao cột i
tới độ cao nhỏ hơn giữa cột l
và r
, tức là min(height[l], height[r]) - height[i]
. Từ đó ta sẽ duyệt từng cột và tính toán lượng nước còn đọng lại trên mỗi cột sử dụng con trỏ kép!
- Sử dụng con trỏ kép đối ngịch
left
vàright
.left
ở đầu vàright
ở cuối. Đi kèm đóleftMax
vàrightMax
ứng với độ cao 2 cột lớn nhất ở 2 đầu trong quá trình duyệt. - Duyệt mảng
height
dựa vào con trỏ képleft
,right
. - Với mỗi lần duyệt có 2 trường hợp xảy ra:
- Cột
leftMax
thấp hơnrightMax
, nên ta sẽ tính nước đọng ở cộtleft
(đơn giản là vì leftMax thấp hơn nên nước sẽ chảy ra hết ở độ caoleftMax
). Lượng nước đọng lại sẽ phải xem xét tới cộtleft + 1
, nếuleftMax > height[left + 1] > hight[i]
thì lượng nước chỉ cao tớiheight[left + 1]
, còn không thì sẽ cao tớileftMax
, cộng thêm vào kết quảans
. - Cột
leftMax
cao hơnrightMax
, suy luận tương tự trường hợp trên
- Cột
- Khi quá trình duyệt kết thúc (tức
left >= right
), trả về kết quảans
.
Ý tưởng 2: Code
class Solution:
def trap(self, height: List[int]) -> int:
if not height:
return 0
left, right = 0, len(height) - 1
leftMax, rightMax = height[left], height[right]
res = 0
while left < right:
if leftMax < rightMax:
left += 1
leftMax = max(leftMax, height[left])
res += leftMax - height[left]
else:
right -= 1
rightMax = max(rightMax, height[right])
res += rightMax - height[right]
return res
Ý tưởng 2: Độ phức tạp
- Độ phức tạp thời gian: , trong đó là độ dài của mảng
height
. - Độ phức tạp không gian: .