Divide and Conquer
문제를 작은 2개의 문제로 분리하고 각각을 해결한 다음, 결과를 모아서 원래의 문제를 해결하는 전략
- 영역을 두개의 sub problem으로 쪼갠다. 이때, 쪼갠 영역의 크기는 최대한 같게 한다. ➡ MergeSort
- 쪼갠 영역을 합병하면서 정렬한다. ➡ Merge
void mergeSort(int arr[], int left, int right){
if(left < right){
int mid = (left+right) / 2;
mergeSort(arr, left, mid);
mergeSort(arr, mid+1, right);
merge(arr, left, mid, right);
}
}
void merge(int arr[], int left, int mid, int right){
int ll = mid-left+1; // left array length
int rl = right-mid; // right array length
int L[ll], R[rl];
for(int i=0; i<ll; i++){
L[i] = arr[left+i];
}
for(int j=0; j<rl; j++){
R[j] = arr[mid+1+j];
}
int i=0, j=0, k=left;
while(i<ll && j<rl){
if(L[i] <= R[j]){
arr[k] = L[i++];
}
else{
arr[k] = R[j++];
}
k++;
}
while(i<ll){
arr[k++] = L[i++];
}
while(j<rl){
arr[k++] = R[j++];
}
}
비교횟수 : log₂n
레코드의 개수 n이 2의 거듭제곱이라고 가정했을 때, n = 2^k
라고 표현할 수 있다.
n = 2^3
의 경우, 2^3 -> 2^2 -> 2^1 -> 2^0
순으로 줄어들어 순환 호출의 깊이가 3이다.
이를 일반화 하면, n = 2^k
이므로 호출의 깊이는 k
이다.
이 때, k = log₂n
이므로 비교횟수는 log₂n
이다.
각 순환 호출 단계의 비교 연산 : n
각 순환 호출에서 전체 리스트의 거의 모든 레코드를 비교해야 하므로 n번의 비교가 발생한다.
따라서 시간복잡도는 순환 호출의 깊이 * 각 순환 호출 단계 비교 연산 = nlog₂n
가 된다.
Best case :
O(nlog₂n)
Worst case :O(nlog₂n)
Average case :O(nlog₂n)
O(n)