分治法最常用的就是将规模为n的实例划分成两个n规模为n/2的实例 。推广到一般的情况,我们可以将规模为n的实例划分为b个规模为n/b的实例。这样对于算法的运行时间存在递推式:T(n) = aT(n/b)+f(n),这个式子又被称为通用分治递推式。
我们假定递推式中的f(n)∈O(n^d),其中d>=0,那么:
所以,对于等分的T(n) = 2T(n/2) + 1,因为a=2,b=2,d=0,并且a > b^d
则T(n) = O(n);
上面这个式子就是用来求解递推式结果的。
归并排序:(时间复杂度O(nlogn))
对于一个需要排序的数组a[0 - n-1],先将数组一分为二a[0 - n/2-1]和a[n/2+1 - n],对子数组排序,之后合并为一个有序数组
import java.util.Arrays;public class Main {// 合并两个有序数组public static void merge(int[] a, int low, int mid, int high) {int[] temp = new int[high - low + 1];int i = low;// 左指针int j = mid + 1;// 右指针int k = 0;// 把较小的数先移到新数组中while (i <= mid && j <= high) {if (a[i] < a[j]) {temp[k++] = a[i++];} else {temp[k++] = a[j++];}}while (i <= mid) {temp[k++] = a[i++];}while (j <= high) {temp[k++] = a[j++];}// 把新数组中的数覆盖a数组for (int k2 = 0; k2 < temp.length; k2++) {a[k2 + low] = temp[k2];}}// 递归分解数组,当待排序的序列长度为1时,判定为有序public static void mergeSort(int[] a, int low, int high) {int mid = (low + high) / 2;if (low < high) {// 左边mergeSort(a, low, mid);// 右边mergeSort(a, mid + 1, high);// 左右归并merge(a, low, mid, high);System.out.println(Arrays.toString(a));}}public static void main(String[] args) {int[] a = {8, 3, 2, 9, 7, 1, 5, 4};mergeSort(a, 0, a.length - 1);System.out.println("排序结果:" + Arrays.toString(a));}
}
归并排序在最坏情况下的键值比较次数十分接近基于比较的排序算法在理论上能够达到的最少次数。
此外快速排序和堆排序的时间复杂度也是O(nlogn),但是相比来说,归并排序在于其稳定性