Programming/CodingTest
[Leetcode 42] Trapping Rain Water
콩순이컴퓨터
2025. 2. 5. 19:05
https://leetcode.com/problems/trapping-rain-water/description/
1. 문제설명
- 각 높이를 나타내는 지도가 주어졌을 때, 얼만큼 물이 담길 수 있는지 계산
2. 문제해결
[stack 이용]
class Solution:
def trap(self, height: List[int]) -> int:
stack = []
water = height.copy()
for i, h in enumerate(height):
if stack and stack[-1][1] <= h:
while stack and stack[-1][1] <= h:
cur_i, cur_h = stack.pop()
if stack:
cur_i = stack[-1][0]
for j in range(cur_i+1, i):
water[j] = h
else:
for j in range(cur_i, i):
water[j] = cur_h
stack.append([i, h])
result = 0
for i in range(len(water)):
result += (water[i]-height[i])
return result
- 현재 높이랑 마지막에 저장된 높이랑 비교하는 과정이 필요하므로 stack 이용
- stack이 들어 있고 현재 높이가 stack의 맨 끝 높이보다 크거나 같으면 pop 반복
- pop 후에 stack 확인
- stack이 비어 있으면 현재 높이보다 모두 작은 높이이므로 마지막에 pop된 높이로 모두 저장 (stack의 맨 앞 요소는 stack의 담긴 높이들 중 가장 높음)
- stack이 남아 있으면 현재 높이보다 더 큰 높이가 있으므로 현재 높이로 물 채우기
- 어디서부터 어디까지 채울지 범위 잘 생각하기
- 마지막에 벽의 높이 - 저장된 높이로 갱신
[투 포인터 이용]
class Solution:
def trap(self, height: List[int]) -> int:
left_max = height[0]
right_max = height[-1]
l = 0
r = len(height)-1
water = height.copy()
while l <= r:
if left_max <= right_max:
if height[l] <= left_max:
water[l] = left_max
else:
left_max = height[l]
l += 1
else:
if height[r] <= right_max:
water[r] = right_max
else:
right_max = height[r]
r -= 1
result = 0
for i in range(len(water)):
result += (water[i] - height[i])
return result
"물이 담기려면 양쪽 벽이 세워져 있어야 한다."
- 첫번째 벽 확인
- 왼쪽 최대 높이와 오른쪽 최대 높이를 비교하면서 작은 쪽의 인덱스를 한 칸씩 움직인다.
- 두번째 벽 확인
- 작은 쪽의 현재 높이가 작은 쪽의 최대 높이보다 작으면 물 채우기 (크면 최대 높이 갱신)
ex) 만약 오른쪽의 최대 높이가 왼쪽의 최대 높이보다 더 높으면, 오른쪽 벽에 의해 물이 담길 수 있다. 그리고 왼쪽에도 벽을 세워야 마침내 물을 담을 수 있으므로, 왼쪽 최대 높이와 왼쪽 인덱스에 대해 현재 높이를 비교한다. 최대 높이보다 현재 높이가 더 작아야 물이 담길 수 있으므로 이를 비교한다.