Programming/Algorithm
[Java] 프로그래머스 징검다리
Yejii
2021. 3. 5. 01:39
문제
바위들의 위치가 담긴 배열이 있고, 제거할 바위 수 n가 있다.
바위 배열에서 n개를 제거한 이후 각 지점사이 거리 최솟값 중 가장 큰 값 리턴해라.
- distance : 도착지점까지의 거리 1~10억
- rocks 요소 개수 : 1~5만
- n 제거할 바위 개수 : 1 ~5만
1) 조합
처음엔 단순하게 n개의 숫자 중 n개를 고르는 시행 만든 뒤 최댓값을 비교하는 방식이 떠올랐다.
하지만 input 값이 커진다면 조합의 경우의 수가 매우 커지기 때문에 효율적인 방식이 아니다.
2) 이진탐색
최소거리를 탐색기준으로 설정한 뒤
추정한 거리로 바위 개수를 세고, '추정한 바위 개수' >= '바위 총개수 - n' 가 남아있어야 최소거리 조건을 만족한다.
조건을 만족한 값들 중 최댓을 구해서 리턴하면 된다.
*isPossible()의 curr 초기화에서 좀 헤맸다. 1번 바위를 반드시 고르는 것이 아니므로 curr= 추정한 최소거리. 로 초기화한 후 시작해야 함
코드
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int distance = 25;
int[] rocks = {2, 14, 11, 21, 17};
int n = 2;
// Arrays.sort(rocks);
System.out.println(solution(distance, rocks, n));
}
static int solution(int distance, int[] rocks, int n) {
Arrays.sort(rocks);
long smallest = 1, biggest = distance; // 범위 설정
int answer = 0;
while (smallest <= biggest) {
long mid = (smallest + biggest) / 2;
if (isPossible(mid, rocks, n)){
answer = (int) Math.max(mid, answer);
smallest = mid + 1;
} else{
biggest = mid - 1;
}
}
return answer;
}
static boolean isPossible(long target, int[] rocks, int n){
long curr = target;
int rock_cnt = 0;
for (int i = 0; i < rocks.length; i++) {
if (curr <= rocks[i]){
rock_cnt++;
curr = rocks[i] + target;
}
}
return rock_cnt >= rocks.length - n; // check
}
}