算法设计
分治法
将原问题分解为几个规模更小的子问题,递归地求解这些子问题,然后通过合并这些子问题来建立原问题的解,这种方法就是 分治法。
分治法在每层递归时都有三个步骤:
分解 原问题为若干个子问题
解决 这些子问题。递归地求解子问题,当子问题的规模足够小时,直接求解子问题
合并 这些子问题以得到原问题的解
其中, 归并排序 完全符合分治法:
void merge(int arr[], int start, int mid, int end) {
int ln = mid - start + 1;
int rn = end - mid;
int left[ln], right[rn];
for (int i = 0; i < ln; i++) left[i] = arr[start + i];
for (int j = 0; j < rn; j++) right[j] = arr[mid + j +1];
int i = 0;
int j = 0;
int k = start;
while (i < ln && j < rn) {
if (left[i] <= right[j]) {
arr[k] = left[i];
i++;
} else {
arr[k] = right[j];
j++;
}
k++;
}
while (i < ln) {
arr[k] = left[i];
i++;
k++;
}
while (j < rn) {
arr[k] = right[j];
j++;
k++;
}
}
void mergeSort(int arr[], int start, int end) {
if (start < end) {
int mid = start + (end - start) / 2;
mergeSort(arr, start, mid);
mergeSort(arr, mid + 1, end);
merge(arr, start, mid, end);
}
}
分治法的需要的时间
假设 \(T(n)\) 是规模为 \(n\) 的一个问题的运行时间,对于规模足够小的问题(此时 \(n <= c\) )求解需要的时间为 \(O(1)\) ,将原问题分解为 \(a\) 个子问题,每个子问题是原问题规模的 \(\frac{1}{b}\);分解子问题需要的时间为 \(D(n)\) ,合并解需要的时间为 \(C(n)\) 。则:
\[\begin{split}\left\{
\begin{array}{lcr}
O(1) && n \leq c\\
aT(\frac{n}{b}) + D(n)+C(n) && n \ge c
\end{array}
\right.\end{split}\]