반응형
소개
- 알고리즘 스터디를 참여하며 작성하는 TIL입니다.
- TIL이란? 'Today I Learned'의 약자로, 한국어로 번역하면 '오늘 내가 배운 것'이란 의미입니다.
- 제가 오늘 하루 배운 것 혹은 경험하고 느낀 것들을 기록하고 회고하는 습관을 기르기 위한 글입니다.
문제 & 키워드
- 프로그래머스 - 징검다리 (문제 링크)
- 이진 탐색
- 최적화 문제
문제 설명
출발지점부터 distance만큼 떨어진 곳에 도착지점이 있습니다. 그리고 그사이에는 바위들이 놓여있습니다. 바위 중 몇 개를 제거하려고 합니다.
예를 들어, 도착지점이 25만큼 떨어져 있고, 바위가 [2, 14, 11, 21, 17] 지점에 놓여있을 때 바위 2개를 제거하면 출발지점, 도착지점, 바위 간의 거리가 아래와 같습니다.
제거한 바위의 위치 | 각 바위 사이의 거리 | 거리의 최솟값 |
[21, 17] | [2, 9, 3, 11] | 2 |
[2, 21] | [11, 3, 3, 8] | 3 |
[2, 11] | [14, 3, 4, 4] | 3 |
[11, 21] | [2, 12, 3, 8] | 2 |
[2, 14] | [11, 6, 4, 4] | 4 |
위에서 구한 거리의 최솟값 중에 가장 큰 값은 4입니다.
출발지점부터 도착지점까지의 거리 distance, 바위들이 있는 위치를 담은 배열 rocks, 제거할 바위의 수 n이 매개변수로 주어질 때, 바위를 n개 제거한 뒤 각 지점 사이의 거리의 최솟값 중에 가장 큰 값을 return 하도록 solution 함수를 작성해주세요.
제한사항
- 도착지점까지의 거리 distance는 1 이상 1,000,000,000 이하입니다.
- 바위는 1개 이상 50,000개 이하가 있습니다.
- n은 1 이상 바위의 개수 이하입니다.
입출력 예
distance rocks n return
25 | [2, 14, 11, 21, 17] | 2 | 4 |
입출력 예 설명
문제에 나온 예와 같습니다.
문제 접근
이 문제는 주어진 바위들을 제거하여 각 지점 사이의 거리의 최솟값을 최대화하는 문제입니다. 이를 해결하기 위해 이진 탐색을 활용할 수 있습니다.
- 바위 정렬
- 주어진 바위의 위치를 오름차순으로 정렬합니다.
- 이진 탐색 범위 설정
- 최소 거리 left는 0으로 설정하고, 최대 거리 right는 도착지점까지의 거리로 설정합니다.
- 중간값 계산
- 이진 탐색의 중간값을 계산하여, 해당 값이 각 지점 사이의 거리의 최솟값으로 설정할 수 있는지 확인합니다.
- 거리 검증
- 바위를 순서대로 확인하면서, 중간값보다 작은 거리를 유지하기 위해 필요한 제거된 바위의 수를 계산합니다.
- 최적화된 거리 갱신
- 제거된 바위의 수가 조건을 만족하는지 확인하고, 만족하면 최적의 거리를 갱신하며 탐색 범위를 조정합니다.
풀이
import java.util.*;
class Solution {
public int solution(int distance, int[] rocks, int n) {
// 예외 처리
if (rocks.length == n) return distance;
// 1. 바위 정렬
Arrays.sort(rocks);
// 각 지점 사이의 거리 계산
int[] d = new int[rocks.length + 1];
d[0] = rocks[0];
d[d.length - 1] = distance - rocks[rocks.length - 1];
for (int i = 1; i < rocks.length; i++) {
d[i] = rocks[i] - rocks[i - 1];
}
// 2. 이진 탐색 범위 설정
int left = 0;
int right = distance;
// 3. 이진 탐색 수행
while (left < right) {
int mid = (left + right) / 2;
int removedStone = 0;
int cur = 0;
// 4. 거리 검증
for (int i = 0; i < d.length; i++) {
cur += d[i];
if (cur < mid) {
removedStone++;
} else {
cur = 0;
}
}
// 5. 최적화된 거리 갱신
if (removedStone < n) {
left = mid + 1;
} else {
right = mid;
}
}
return left - 1;
}
}
풀이 설명
- 바위 정렬
- 주어진 바위의 위치를 오름차순으로 정렬합니다.
- 이진 탐색 범위 설정
- 최소 거리 left를 0으로 설정하고, 최대 거리 right를 도착지점까지의 거리로 설정합니다.
- 이진 탐색 수행
- left가 right보다 작을 때까지 이진 탐색을 수행합니다.
- 중간값 mid를 계산하고, 이 값을 기준으로 각 지점 사이의 거리의 최솟값을 설정합니다.
- 거리 검증
- 각 바위 사이의 거리를 합산하면서, 중간값보다 작은 거리를 유지하기 위해 필요한 제거된 바위의 수를 계산합니다.
- 제거된 바위의 수가 n보다 작으면 left를 mid + 1로 설정하고, 그렇지 않으면 right를 mid로 설정합니다.
- 최적화된 거리 갱신
- 탐색 범위를 조정하여 가능한 최적의 거리를 찾습니다.
- 최종적으로 left - 1을 반환하여 바위를 제거한 뒤 각 지점 사이의 거리의 최솟값 중 가장 큰 값을 반환합니다.
마무리하며
- 이번 문제를 통해 이진 탐색을 활용한 최적화 문제 해결 방법을 익힐 수 있었습니다.
- 문제를 해결하기 위해 바위 간의 거리를 계산하고 조건에 맞게 탐색 범위를 조정하는 과정이 중요함을 배웠습니다.
반응형