우리가 배열을 선형으로 접근할떄는 Index를 순서대로 조회하게 된다.
하지만 만약 정렬이 되어있는 배열이라면 선형으로 탐색하는 방법보다 빠르게 조회할 수 있다.
int arr[] = { 17, 28, 43, 67, 88, 92, 100 };
43
을 검색해보자.코드로 구현한다면 다음과 같다.
@SpringBootApplication
public class BinaryTestApplication {
s![](https://velog.velcdn.com/images/rjsgh17/post/85b62926-71ce-4b61-b1a4-7ab8a7ea97db/image.png)
;
public static void main(String[] args) {
System.out.println("반복 호출을 이용한 이진 탐색");
System.out.println("index = " + binarySearch2(43, 0, arr.length - 1)); // 4
}
// 반복적 탐색
static int binarySearch2(int key, int low, int high) {
int mid;
while (low <= high) {
mid = low + (high - low) / 2;
if (key == arr[mid]) {
return mid;
} else if (key < arr[mid]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return -1; // 탐색 실패의 경우
}
결과는 다음과 같다.
반복 호출을 이용한 이진 탐색
index = 2
• 오늘 동빈이는 여행 가신 부모님을 대신해서 떡집 일을 하기로 했습니다. 오늘은 떡볶이 떡을 만드는 날입 니다. 동빈이네 떡볶이 떡은 재밌게도 떡볶이 떡의 길이가 일정하지 않습니다. 대신에 한 봉지 안에 들어가 는 떡의 총 길이는 절단기로 잘라서 맞춰줍니다.
• 절단기에 높이(H)를 지정하면 줄지어진 떡을 한 번에 절단합니다. 높이가 H보다 긴 떡은 H 위의 부분이 잘릴 것이고, 낮은 떡은 잘리지 않습니다.
• 예를 들어 높이가 19, 14, 10, 17cm인 떡이 나란히 있고 절단기 높이를 15cm로 지정하면 자른 뒤 떡의 높이는 15, 14, 10, 15cm가 될 것입니다. 잘린 떡의 길이는 차례대로 4, 0, 0, 2cm입니다. 손님은 6cm 만큼의 길이를 가져갑니다.
• 손님이 왔을 때 요청한 총 길이가 M일 때 적어도 M만큼의 떡을 얻기 위해 절단기에 설정할 수 있는 높이의 최댓값을 구하는 프로그램을 작성하세요
입력조건
• 첫째 줄에 떡의 개수 N과 요청한 떡의 길이 M이 주어집니다.
(1 ≤ N ≤ 1,000,000, 1 ≤ M ≤ 2,000,000,000)• 둘째 줄에는 떡의 개별 높이가 주어집니다. 떡 높이의 총합은 항상 M 이상이므로, 손님은 필요한 양만 큼 떡을 사갈 수 있습니다. 높이는 10억보다 작거나 같은 양의 정수 또는 0입니다.
출력 조건
• 적어도 만큼의 떡을 집에 가져가기 위해 절단기에 설정할 수 있는 높아의 최댓값을 출력합니다
입력 예시 :
고객이 가져온 떡 = {19,15,10,17}, N = 4 , M = 6
출력 예시 :
15
본문제의 출처 및 영상 여기를 참조해주세요 해설도 영상입니다~!!!
Scanner sc = new Scanner(System.in);
//떡의 개수 = N 요청한 떡의 길이 (M)
int n = sc.nextInt();
int m = sc.nextInt();
//r각 떡의 개별 높이 정보
int[] arr1 = new int[n];
for (
int i = 0;
i < n; i++) {
arr1[i] = sc.nextInt();
}
//이진 탐색을 위한 시작점과 끝점 설정
int start = 0;
int end = (int) 1e9; //10억
//이진 탐색 수행( 반복적 )
int result = 0;
while (start <= end) {
long total = 0;
int mid = (start + end) / 2;
for (int i = 0; i < n; i++) {
//잘랐을 때의 떡의 양 계산
if (arr1[i] > mid) total += arr[i] - mid;
}
if (total < m) { //떡의 양이 부족한 경우 더 많이 자르기 (왼쪽 부분 탐색)
end = mid - 1;
} else { // 떡의 양이 충분할 경우 덜 자르기(오른쪽 부분 탐색)
result = mid; // 최대한 덜 잘랐을 떄를 구하는 내용이므로 현제 mid값을 기록
start = mid + 1;
}
}
System.out.println(result);
}
시작점과 끝점을 mid값을 조건에 따라 변경하면서 이분탐색을 진행 할 수 있다. 개념자체는 어렵지 않으나 문제에 이분탐색을 적용하는게 어렵다.
예제를 추가적으로 풀요하다.