Leetcode
[Leetcode] 42. Trapping Rain Water - JS
Wix
2024. 9. 18. 10:00
1. 문제 분석
문제분석
--------------------
- 양의 정수 n으로 이루어진 배열이 주어진다.
- n은 바의 높이를 의미한다.
- 비가 오고 난 후 얼마나 많은 양의 물을 가둘 수 있는지 계산하라.
제한조건
--------------------
- n == height.length
- 1 <= n <= 2 * 10^4
- 0 <= height[i] <= 10^5
2. 접근 방법
접근방법
--------------------
물을 가두기 위해서는 높이를 가진 왼쪽 바와 오른쪽 바가 존재해야한다.
height = [2,1,0,1,3,2]
파란색 부분에 물을 채우기 위해선 어떻게 해야할까?
우선 index 2인 곳의 양옆에는 높이가 1인 바가 있어서 물이 1이 있다는 것을 알 수 있다.
하지만 index 1의 높이가 1이면 어떨까?
이때는 왼쪽에 높이가 2인 인접한 바가 있고
오른쪽에는 높이가 3인 바가 있어서 물이 유지될 수 있다.
물과 바 사이의 어느정도 거리가 있을 때 물을 가둘 수 있는지는 어떻게 판단할 수 있을까?
방법은 왼쪽과 오른쪽의 최대 높이값을 유지하는 것이다.
Two Pointer를 사용하여 문제를 해결해보자.
[2,1,0,1,3,2]
L R
L = 0 // 현재 왼쪽 바
R = height.length - 1 // 현재 오른쪽 바
leftMax = 2 // 왼쪽 바 최대 높이값
rightMax = 2 // 오른쪽 바 최대 높이값
water = 0 // 물의 양
왼쪽 포인터(L) < 오른쪽 포인터(R)을 만족하면 반복한다.
1. leftMax, rightMax 중 작은 값을 가진 포인터를 이동시킨다.
더 작은 값의 포인터를 이동시키는 이유는 물이 바 사이에 갇힐 때,
물을 가질 수 있는 높이가 둘 중 더 작은 바의 높이만큼 가질 수 있기 때문이다.
leftMax = 2, rightMax = 2로 동일하기에 둘중 하나의 포인터(R)를 이동시켰다.
[2,1,0,1,3,2]
L R
2. R 포인터가 이동했으니 rightMax 값과 비교하여 더 큰 값으로 갱신해준다.
rightMax = 3
3. 물을 계산한다.
water += rightMax - R = 3 - 3 = 0
오른쪽 바를 움직였으니 오른쪽 바의 최대값과 현재 오른쪽 바와의 차이를 구하면 된다.
이 때 왼쪽 바는 이미 높이가 오른쪽 바 보다 크거나 같으니 상관하지 않아도 된다.
이렇게 한번의 반복이 끝나고
L < R 조건을 만족하지 않을 때 까지 반복한다.
결과적으로 L < R 조건을 만족하지 않아서 반복이 종료되면 그 때의 물을 반환한다.
3. 코드
var trap = function(height) {
let left = 0;
let right = height.length - 1;
let leftMax = height[left];
let rightMax = height[right];
let water = 0;
while (left < right) {
if (leftMax < rightMax) {
left++;
leftMax = Math.max(leftMax, height[left]);
water += leftMax - height[left];
} else {
right--;
rightMax = Math.max(rightMax, height[right]);
water += rightMax - height[right];
}
}
return water;
};
물 높이를 구하기 위해 왼쪽, 오른쪽으로 나눠서
한쪽의 최대 높이값과 현재 막대의 높이값의 차를 가지고
물의 양을 구하고 이를 누적하여 답을 도출해내었다.
4. 복잡도 분석
- 시간복잡도: O(n)
- 공간복잡도: O(1)
30분동안 방법을 고민해도 갈피를 아예 잡지 못하였다. 물을 어떻게 하면 가둘 수 있을까?를 똑같이 고민했고, 바로 인접한 경우의 물은 쉽게 구할 수 있다고 생각했다. 하지만 막대 사이의 거리가 존재할 때의 물을 어떻게 구할 수 있을지 생각하지 못했다.
Two pointer를 이용해 왼쪽, 오른쪽 구간을 나누고 물 높이를 구할 때, 왼쪽 또는 오른쪽의 최신의 최대 높이값을 추적하여 현재 바의 높이값과 비교하여 물의 양을 구할 수 있다는 방법도 있다는 것을 알게되었다.
Two pointer에 대해 좀 더 문제를 풀어보면서 익혀야겠다.