2024년 4월 12일 (금)
Leetcode daily problem
https://leetcode.com/problems/trapping-rain-water/?envType=daily-question&envId=2024-04-12
각 막대의 너비가 1인 높이를 나타내는 음이 아닌 정수 n으로 구성된 배열이 주어 질 때, 해당 배열에 얼마나 많은 물을 가둘 수 있는지 계산한다.
two pointer 혹은 stack
해당 문제는 stack을 이용해서 주어진 배열에서 각 지점의 높이를 토대로 물이 쌓일 수 있는 부분을 파악해서 해결할 수 있다.
class Solution:
def trap(self, height: List[int]) -> int:
if not height:
return 0
stack = []
water = 0
for i in range(len(height)):
while stack and height[i] > height[stack[-1]]:
top = stack.pop()
if not stack:
break
distance = i - stack[-1] -1
h = min(height[i], height[stack[-1]])- height[top]
water += distance * h
stack.append(i)
return water
각 높이를 스택에 push하면서 현재 높이가 스택의 top보다 큰 경우, 스택에서 top을 pop하여 현재 높이와 스택의 top 사이에 빗물이 쌓일 수 있는 부분을 계산하는 방식이다.
시간 복잡도
배열을 한 번 순회하면서 스택을 조작하고 계산하는 과정이 있다. height 배열의 모든 요소를 한 번씩 방문하므로, 배열의 길이가 n일 때 O(n)의 시간이 소요된다. 시간 복잡도는 O(n)이다.
공간 복잡도
주어진 배열에 대해 스택을 사용하여 최악의 경우에는 배열과 동일한 길이의 스택이 필요하기 때문, 공간 복잡도는 배열의 크기에 선형적으로 증가한다.
공간 복잡도는 O(n)이다.
그외에 two pointer로 해결할 수 있는 방법이다.
class Solution:
def trap(self, height: List[int]) -> int:
if not height:
return 0
l,r = 0, len(height)-1
leftmax, rightmax = height[l], height[r]
water = 0
while l<r:
if leftmax < rightmax:
l+=1
leftmax = max(leftmax, height[l])
water += leftmax - height[l]
else:
r -=1
rightmax = max(rightmax, height[r])
water += rightmax - height[r]
return water