오늘의 학습 키워드 : 이분 탐색 , 파라메트릭 서치
1. 문제 : 백준 16401 과자 나눠주기
2. 내 풀이
이분 탐색에 대한 개념은 알고 있었지만 파타메트릭 서치(이분탐색의 하위개념)에 대해서는 알지 못했다.
그래서 공부를 좀 하느라 시간이 걸렸다.
파라메트릭 서치 같은 경우는 "최적화문제"를 "결정 문제"로 바꿔서 해결하는 알고리즘이다. 이 개념은 유튜브 보고 이해를 했다..
결론적으로는 이분 탐색같은 경우는 입력받은 배열 같이 특정 값을 찾아 반절씩 쪼개면, 파라매트릭 서치는 배열이 아니라 내가 원하는 정답
이진탐색 | 파라매트릭 서치 | |
목적 | 특정 값을 찾기 | 조건을 만족하는 최대 or 최소값 찾기 |
탐색 대상 | 배열에 있는 특정 값 | 정답 후보(값 자체)가 범위에 있음 |
기준 조건 | arr[mid] == target | check(mid)가 조건 만족 여부 |
탐색 방식 | 값이 있는지 여부 | 조건 만족 여부를 기준으로 left/right 이동 |
자주 나오는 문제 | 정렬된 배열에서 특정 값 찾기 | 최대 길이, 최소 비용, 최대 거리, 최대 높이 |
- 이분 탐색 : 특정값을 찾는 문제 (배열안에 target 값 찾기 )
- 파라매트릭 서치 : 최대 몇 까지 가능? 최소 몇까지? 이런 느낌이다.
- 이분탐색을 풀 때 처럼 파라매트릭 서치도 템플릿은 비슷하다(left, right, mid정하는 그런거,,)
처음에는 입력받은 배열 안에서 탐색을 하려고 하니까 머리가 안돌아갔다. 그래도 좀 공부를 하다보니 이해가 됐다.
애초에 탐색하려는 범위가 과자의 길이 입력받은 값들이 아니라 결국 여기서 제일 큰 과자의 길이가 max가 되고 1~max 사이의 값 중에서 탐색을 하면 된다. 정답 후보는 이거다. 그리고 입력받은 과자의 길이들은 mid(target)값을 구할때 과자의 개수(cnt)를 구하는데 활용이 된다.
시간복잡도 = O(N log(N))
3.코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class CT0414 {
static int left = 1;
static int right = 0;
static int mid =0;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int M = Integer.parseInt(st.nextToken()); //조카 수
int N = Integer.parseInt(st.nextToken()); //과자 수
int[] lenarr = new int[N]; // 과자의 각 길이를 담을 배열 선언
st = new StringTokenizer(br.readLine());
for(int i=0; i< N; i++) {
lenarr[i] = Integer.parseInt(st.nextToken());
right = Math.max(right, lenarr[i]); // 제일 큰 값이 들어가게 됌
}
int result = 0;
while(left <= right) {
mid = (left + right) / 2;
int cnt = 0; // 과자를 나눴을 때 과자의 개수
for (int i = 0; i < N; i++) {
cnt = cnt + lenarr[i] / mid;
}
// 이 부분에서 조쿰 오류가 났었다
// if (cnt < M) { // 조카 수 < 과자 수 (과자 길이 중어야함)
// right = mid - 1;
// } else if (cnt > M){ // 조카 수 > 과자 수 (과자 기링 늘려도 됌)
// left = mid + 1;
// } else {
// break;
// }
//개선된 코드
if(cnt < M) {
right = mid - 1;
} else {
result = mid;// 조건 만족하긴 하지만 더 크게 만족하는 값을 찾기 위해
left = mid + 1;
}
}
System.out.println(result);
}
}
- 풀고 나서 보니까 테스트 케이스에서 답이 어떤것은 맞고 틀렸다..
- 조건문에서 아무래도 조건만 맞는다고 끝이 아니라 결국 더 큰 값을 만족해야하기 떄문에 mid값을 보관하고 한번 더 탐색해서 더 만족하는 값을 구할 수 있게 했다.
'Algorithm > 항해99클럽_6기_TIL' 카테고리의 다른 글
99클럽 코테 4일차 TIL - 백준 2559 수열 (0) | 2025.04.04 |
---|