IT/Problem Solving
[LeetCode] Trapping Rain Water (Java)
erinh
2024. 2. 21. 23:57
반응형
문제
문제풀이 1. 두 번 계산해주자
- DP로 풀었다.
- 두 가지 경우를 나누어 앞에서 부터 탐색했을 때와 뒤에서부터 탐색했을 때를 모두 계산해줬다.
처음에 기준 높이를 가지고 앞에서 부터 탐색할 때 기준 높이보다 높거나 같은 막대를 만나지 못하면 계산이 안된다.
따라서 뒤에서 부터도 똑같은 방식으로 탐색을 해주고,
DP배열을 한 번 더 돌아서 각 위치에서 더 낮은 값을 결과값으로 더해줬다.
class Solution {
public int trap(int[] height) {
int currHeight = height[0];
int[][] dp = new int[2][height.length];
dp[0][0] = 0;
dp[1][height.length - 1] = 0;
for (int i = 1; i < height.length; i++) {
if (height[i] >= currHeight) {
dp[0][i] = 0;
currHeight = height[i];
} else {
dp[0][i] = currHeight - height[i];
}
}
currHeight = height[height.length - 1];
for (int i = height.length - 2; i >= 0; i--) {
if (height[i] >= currHeight) {
dp[1][i] = 0;
currHeight =height[i];
} else {
dp[1][i] = currHeight - height[i];
}
}
int result = 0;
for (int i = 0; i < height.length; i++) {
result += Math.min(dp[0][i], dp[1][i]);
}
return result;
}
}
- 사실 풀면서, 이걸 꼭 두 번 돌아야 하나? 한 번 반복문으로 끝낼 수는 없나? 라고 생각했는데,
멋진 풀이가 있어 참고하여 다시 풀어보았다.
문제풀이2. 투 포인터를 이용해 한 번의 반복문으로 끝내자
- 먼저, 주어진 벽의 맨 끝에 포인터를 두고 생각해보자.
- 왼쪽이 오른쪽보다 벽의 높이가 더 낮다면, 우리는 왼쪽부터 탐색을 시작할 것이다.
반대로 오른쪽이 왼쪽보다 벽의 높이가 더 낮다면, 오른쪽부터 탐색을 시작해야 물이 얼마나 고였는지를 탐색할 수 있다.
이런 원리를 통해 왼쪽과 오른쪽에 포인터를 두고, 더 낮은 쪽부터 옆 방향으로 탐색을 진행해주는 것이다.
- 각 포인터가 만나기 전까지만 탐색을 진행해주고, 왼쪽과 오른쪽에서 가장 높은 길이는 얼마인지는 계속 탐색해주면서 진행해준다.
왼쪽/오른쪽 높이의 최대값이 더 낮은 애부터 탐색을 하면서 결과값에 값을 더해준다.
class Solution {
public int trap(int[] height) {
int leftIdx = 0, rightIdx= height.length - 1; // 각 포인터의 인덱스
int leftMax = Integer.MIN_VALUE, rightMax = Integer.MIN_VALUE; // 각 파트의 최대 높이
int result = 0; // 결과값 저장
while (leftIdx < rightIdx) {
leftMax = Math.max(leftMax, height[leftIdx]); // 각 파트의 최대 높이 갱신
rightMax = Math.max(rightMax, height[rightIdx]);
// 낮은 쪽 먼저 탐색하여 결과값에 저장해줌
result += (leftMax < rightMax) ? leftMax - height[leftIdx++] : rightMax - height[rightIdx--];
}
return result;
}
}
- 결과는 비슷하다. 문제의 데이터 범위가 굉장히 작기도 해서 iterator가 1번이냐 3번이냐로는 많은 성능 차이가 발생하지 않는 것 같다.
반응형