이진 탐색(Binary Search)
- 정렬된 배열에서 특정 값을 찾는 알고리즘
- 탐색 범위를 절반씩 줄여 나가기 때문에 선형탐색에 비해 빠른 속도 보장
- 시간 복잡도 O(logn) 상대적으로 매우 빠름
이때 선형 탐색이란?
- 배열(Array)이나 리스트(List)와 같은 데이터 구조에서 처음부터 끝까지 하나씩 값을 비교하면서 찾는 값을 찾을 때까지 탐색
- 즉, 정렬되지 않은 상태에서 찾는 것으로 이진탐색과 다른점시간 복잡도 O(n)

- 배열의 ‘중간 값’ 을 선택하여 찾고자 하는 값과 비교
- 만약 중간 값이 찾고자 하는 값보다 크면 ‘배열 왼쪽 부분’에서 탐색을 진행
- 중간 값이 찾고자 하는 값보다 작으면 ‘배열 오른쪽 부분’에서 탐색을 진행
- 이 과정에서 찾고자 하는 값이 나올 때까지 반복
이진탐색 과정
정렬된 배열 array에서 key 값을 찾는 이진 탐색을 구현하는 과정
- 탐색의 대상이 되는 자료들이 array[low]에서부터 array[high]에 들어있다고 가정하자. (즉, 정렬이 되어있어야함)
- 즉, 어떤 시점에서 탐색되어야할 범위는 low ~ high까지가 된다.
- 맨처음 low에는 0번 인덱스의 값, high에는 n-1번 인덱스의 값 들어간다.
- low와 high 값에 의거해 중간값 mid 값은 (low + high)/2이다.
- 즉, array[low] ~ array[high]까지의 탐색은
- array[low] ~ array[middle-1] + array[middle+1] + array[high]까지의 탐색
- array[mid] 값과 구하고자 하는 key 값을 비교한다.
- key > mid
- 구하고자 하는 값이 중간값보다 높다면 low를 mid+1로 만들어 줌 (왼쪽 반을 버림)
- key < mid
- 구하고자 하는 값이 중간값보다 낮다면 high를 mid-1로 만들어 줌(오른쪽 반을 버림)
- key == mid
- 구하고자 하는 값을 찾음 중간값 리턴
- key > mid
- low>high가 될 때까지 1~3번을 반복하면서 구하고자 하는 값을 찾는다.
- 이때까지 못 찾으면 탐색 실패 -1, false, error 등 리턴
순환 호출을 이용한 이진 탐색 구현

//시작 인덱스와 마지막 인덱스 값을 지정
int low = 0;
int high = array.length - 1;
int binarySearch1(int key, int low, int high) {
int mid;
if(low <= high) {
mid = (low + high) / 2;
if(key == arr[mid]) {
return mid; //탐색 성공
} else if (key < arr[mid]) {
//왼쪽 부분 arr[0] ~ arr[mid-1] 탐색
return binarySearch1(key, low, mid - 1);
} else {
//오른쪽 부분 arr[mid+1] ~ arr[high] 탐색
return binarySearch1(key, mid + 1, high);
}
}
return -1; //탐색 실패
}
반복을 이용한 이진 탐색 구현
- 반복 구조를 사용하는 것이 재귀 호출로 구현하는 것보다 효율적이다.

//시작 인덱스와 마지막 인덱스 값을 지정
int low = 0;
int high = array.length - 1;
int binarySearch2(int key, int low, int high) {
int mid;
//높은 인덱스(high)가 낮은 인덱스(low)보다 크거나 같은지 확인
while(low <= high) {
mid = (low + high) / 2;
if(key == arr[mid]) {
return mid;
} else if(key < arr[mid]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return -1; //탐색 실패
이진 탐색의 문자열 탐색
- 문자열 배열의 경우 이진/이분 탐색을 사용하는 경우
- Arrays.binarySearch() 함수를 이용하자!
Arrays.binarySearch()
- public static int binarySearch(Object[] a, Object key)
- 매개변수로 주어진 배열에서 원하는 값을 이진 탐색하여 인덱스를 반환 (int)
- 해당 원소가 배열에 없으면 음수를 반환
- 이진 탐색을 하기전 반드시 배열 정렬해야함
프로그래머스 [입국 심사]
https://school.programmers.co.kr/learn/courses/30/lessons/43238
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
문제
n명이 입국심사를 위해 줄을 서서 기다리고 있습니다. 각 입국심사대에 있는 심사관마다 심사하는데 걸리는 시간은 다릅니다.
처음에 모든 심사대는 비어있습니다. 한 심사대에서는 동시에 한 명만 심사를 할 수 있습니다.
가장 앞에 서 있는 사람은 비어 있는 심사대로 가서 심사를 받을 수 있습니다.
하지만 더 빨리 끝나는 심사대가 있으면 기다렸다가 그곳으로 가서 심사를 받을 수도 있습니다.
모든 사람이 심사를 받는데 걸리는 시간을 최소로 하고 싶습니다.
입국심사를 기다리는 사람 수 n
각 심사관이 한 명을 심사하는데 걸리는 시간이 담긴 배열 times
모든 사람이 심사를 받는데 걸리는 시간의 최솟값을 return
입출력 예
| n | times | return |
| 6 | [7, 10] | 28 |
- 가장 첫 두 사람은 바로 심사를 받으러 갑니다.
- 7분이 되었을 때, 첫 번째 심사대가 비고 3번째 사람이 심사를 받습니다.
- 10분이 되었을 때, 두 번째 심사대가 비고 4번째 사람이 심사를 받습니다.
- 14분이 되었을 때, 첫 번째 심사대가 비고 5번째 사람이 심사를 받습니다.
- 20분이 되었을 때, 두 번째 심사대가 비지만 6번째 사람이 그곳에서 심사를 받지 않는다.
- 1분을 더 기다린 후에 첫 번째 심사대에서 심사를 받으면 28분에 모든 사람의 심사가 끝납니다.
풀이 과정
- times의 배열의 최고 값을 기준으로 이분 탐색을 하면서
- mid 값으로 각 심사관이 몇명을 검색할 수 있냐만 계산해서 최솟값 구해보자
- times를 오름차순으로 먼저 정렬
- 시간의 최솟값, 최댓값 정하기
- min = 1 (1초)
- max = times[times.length - 1] * n
- 가장 느린 심사관(times[times.length -1])이 n명을 전부 심사하는 경우
- 필요한 값 선언
- mid : 중간 값
- sum : 주어진 시간 mid 안에 총 몇명이 심사 받을 수 있는지 계산
- answer : 조건을 만족 하는 시간중 가장 짧은 시간을 저장
- while문은 min ≤ max 일때
- mid = (min + max) / 2;
- 현재 검사하고자 하는 시간
- times 포문으로 sum을 계산해보기
- 각 심사관이 mid 시간동안 몇명을 심사할 수 있는지
- 그것의 합산 sum에 저장
- sum이 n명 보다 크거나 같으면
- 최소 시간을 줄여서 더 탐색해보자 ! max = mid - 1
- 그치만 일단 저장하기 answer = mid
import java.util.*;
class Solution {
public long solution(int n, int[] times) {
Arrays.sort(times);
long answer = 0;
long min = 1;
long max = (long)times[times.length-1]*n; //최장시간
long mid;
while (min <= max) {
mid = (left + right)/2; //중간값
long sum = 0; //중간값동안 탐색할 수 있는 총시간
for(int time : times){
sum += mid / time;
}
if(sum >= n){
answer = mid;
max = mid - 1;
}else {
min = mid + 1;
}
}
return answer;
}
}
'공부' 카테고리의 다른 글
| [Spring] Transaction Propagation (1) | 2024.12.16 |
|---|---|
| [Spring] self-invocation (0) | 2024.11.23 |
| Load Balancer & Auto Scaling (1) | 2024.11.06 |
| [JAVA] PriorityQueue - 우선순위 큐 (0) | 2024.07.01 |
| [알고리즘] DP (1) | 2024.05.25 |