티스토리 뷰
리스트를 사용하는 조금 난이도 있는 문제를 가지고 왔다.
벽들의 높이를 리스트로 입력받아, 빗물이 쌓일 수 있는 면적을 구하는 문제이다.
처음에는 한개의 포인터로, 더 높은 벽을 만날 때마다 포인터를 높은 벽의 높이로 갱신하며, 이전 포인터 까지의 격차를 더하여 푸려고 계획했다.
그러나, 포인터를 한개만 사용하면, 가장 높은 벽(예시에서는 3)을 만난 뒤에는 포인터를 갱신할 수 없는 문제가 발생하고, 이 문제를 해결하려면 꽤나 복잡한 로직이 동반된다.
그래서, 가장 높은 벽을 기준으로 양 끝, 두개의 포인터를 이용하여 풀이를 작성했다.
1. 두개의 포인터를 이용하여 풀이
from typing import List
def trap(rain: List[int]) -> int:
sum = 0
left = 0 # left 포인터
right = len(rain) - 1 # right 포인터
left_max = rain[left] # 포인터 위치 벽의 초기 높이
right_max = rain[right] # 포인터 위치 벽의 초기 높이
# left_max와 right_max를 비교하며 더 작은 포인터를 움직이게끔 하면,
# 가장 높은 벽까지 와서 로직이 멈추게 된다.
while left < right:
# 현재 포인터 위치의 벽과 초기 높이를 비교하여 갱신 작업을 진행
left_max = max(left_max, rain[left])
right_max = max(right_max, rain[right])
if rain[left] <= rain[right]:
# 높은 벽의 높이 - 현재 포인터의 높이가 빗물이 쌓일 수 있는 면적이다.
sum += left_max - rain[left]
left += 1
else:
sum += right_max - rain[right]
right -= 1
return sum
if __name__ == '__main__':
rain = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]
print(trap(rain))
위 처럼 두개의 포인터를 이용하여 풀면 O(n)으로 꽤나 효율적인 풀이가 가능하다.
물론 이렇게 두개의 포인터를 이용하는 방법 말고도 다른 효율적인 방법이 존재한다.
2. stack을 이용하여 더 높은 벽(변곡점)을 만날 때마다 stack에 쌓아 놓은 걸 추출하여 계산
from typing import List
def trap(rain: List[int]) -> int:
stack = []
sum = 0
for i in range(len(rain)):
# stack 에 넣어놓은 마지막 위치의 벽과 현재 벽을 비교
while stack and rain[i] > rain[stack[-1]]:
top = stack.pop()
if not len(stack):
break
distance = i - stack[-1] - 1
waters = min(rain[i], rain[stack[-1]]) - rain[top]
sum += distance*waters
stack.append(i)
return sum
if __name__ == '__main__':
rain = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]
print(trap(rain))
이 방법은 인덱스를 증가시킬 때마다 stack에 인덱스 정보를 넣어두고, 변곡점을 만날 때마다, 빗물의 면적을 계산하여 결과를 도출하는 방식이다.
시간 복잡도는 첫번째 풀이와 비슷하나, 개인적으로는 두개의 포인터를 이용하여 풀었던 방식보다 직관성이 좀 떨어지지 않나 싶다. 필자도 처음에는 이런 식의 풀이를 생각했지만, stack을 꺼내는 방식에서 꽤나 해메서...결국 이 방법을 스스로 생각해낼 수는 없었다.
반응형
'[Python] > 선형 자료구조' 카테고리의 다른 글
[Python] 단방향 연결리스트 구현 (0) | 2021.05.12 |
---|---|
[Python] 연결리스트 <Runner 기법> (0) | 2021.05.11 |
[Python] List <자신을 제외한 배열의 곱> (0) | 2021.05.10 |
[Python] List <세 수의 합> (0) | 2021.05.07 |
[Python] List <두 수의 합> (0) | 2021.05.06 |
Comments
최근에 올라온 글
최근에 달린 댓글
TAG
- 인천 구월동 이탈리안 맛집
- redux-thunk
- Promise
- 인천 구월동 맛집
- Async
- AsyncStorage
- 정보보안기사 #실기 #정리
- react
- react-native
- 맛집
- 파니노구스토
- 이탈리안 레스토랑
- javascript
- await
- redux
- Total
- Today
- Yesterday