문제
[분할 정복 알고리즘(Divide and Conquer Algorithm)]
주어진 문제의 크기가 감당하기 어려운 경우 보다 작은 문제로 나누어 해결하는 방법(알고리즘)이다.
이진검색, 퀵정렬, 합병정렬 등이 대표적인 예이다.
[이진 검색(Binary Search)]
이진 검색(탐색) 알고리즘이란 정렬된 데이터 리스트에서
목표값 또는 목표값이 있는 위치를 빠른 시간에 찾는 분할 정복 알고리즘 중에 하나이다.
예를 들어 정렬된 데이터 배열 A[]가 주어지고 목표값 target 을 찾는다고 가정해보자.
이때 첫 번째 원소의 인덱스는 low 이고, 마지막 원소의 인덱스는 high 라고 하자.
이제 이진 검색 알고리즘 프로세스는 다음과 같다.
1. 현재 탐색 구간의 가운데 배열번호(인덱스) mid를 구한다.
mid = (low + high) / 2;
2. A[mid]값과 target값을 비교한다.
(1) 만약 A[mid] == target 이라면 목표값 또는 목표값이 있는 위치를 찾은 것이다.
(2) 만약 A[mid] < target 이라면 low = mid+1로 하여 검색범위를 조정한다.
(3) 만약 A[mid] > target 이라면 high = mid-1로 하여 검색범위를 조정한다.
3. 탐색구간이 남아 있고 목표값을 찾지 못한 동안 1, 2번 프로세스를 반복한다.
만약 low > high 라면(탐색구간이 남지 않는 경우) 목표값이 배열에 없는 경우이다.
위 프로세스는 매 루프마다 탐색해야할 범위가 절반 이하로 줄어든다.
데이터 개수와 최대 탐색수를 표로 비교해보면 아래와 같다.
데이터 수가 2배 늘어날때마다 탐색 수는 1씩 증가하고 있다.
따라서 데이터 수에 따른 탐색수를 일반화 하여 나타내면 밑이 2인 log(n) + 1 임을 알 수 있다.
순차탐색에 비하여 매우 훌륭한 성능을 보여준다.
[이진탐색 의사코드 - loop version]
binarySearch (A[], low, high, target) :
while low <= high :
mid = (low + high) / 2;
if A[mid] == target:
return mid
if A[mid] > target:
high = mid - 1
else:
low = mid + 1
return -1
[이진탐색 의사코드 - recursive version]
binarySearchRecur (A[], low, high, target):
if low > high:
return -1
mid = (low + high) / 2
if A[mid] == target:
return mid
if( A[mid] > target):
return binarySearchRecur(A, low, mid-1, target)
return binarySearchRecur(A, mid+1, high, target)
[문제]
N개의 정렬된 데이터가 주어지고 Q개의 질의가 주어진다.
정렬된 데이터에서 목표값이 있는 위치(인덱스)를 찾는 프로그램을 작성하시오.
입력
첫 행에
두 번째 행에 오름차순으로 정렬된
세 번째 행에
네 번째 행에
출력
배열의 첫번째 원소는
찾는 값이 없는 경우
예제1
5
1 2 3 4 5
3
-5 5 2
-14 1
예제2
8
-7 -5 -3 0 2 4 6 8
5
-3 6 -7 0 8
26 0 3 7