分治法的基本思想
将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同。
一般设计模式
f(p){
递归出口
分解
for(i = 1;i <= k;i++){
yi = f(pi); // for循环的此部分为递归求解过程
}
return merge(y1,...,yk);
例子
1、归并排序
思想:用分治策略实现对n个元素排序
时间复杂度:最好O(nlogn),平均O(nlogn)
实现:
public class MergeSort {
/**
* 入口函数
* @param a
*/
public void MergeSort(int[] a){
int[] temp = new int[a.length];
mergeSort(a,0,a.length-1,temp);
System.out.println(Arrays.toString(a));
}
/**
* 主处理函数
* @param a 输入的数组
* @param start 开始index
* @param end 结束index
* @param temp 临时数组temp
*/
public void mergeSort(int[] a,int start,int end,int[] temp){
// 直到start >= end 递归结束
if(start < end){
int mid = (end+start)/2;
// 递归排序左半部分
mergeSort(a,start,mid,temp);
//递归排序由半部分
mergeSort(a,mid+1,end,temp);
//拍好后把temp的结果更改放到原数组中
mergeArr(a,start,mid,end,temp);
}
}
/**
* 把temp数组中的结果放到a中
* @param a
* @param start
* @param mid
* @param end
* @param temp
*/
public void mergeArr(int[] a,int start,int mid,int end,int[] temp){
int i = start;
int j = mid+1;
int k = 0;
// 所有小的元素放到前面,大的元素放到后面
while(i <= mid && j <= end){
if(a[i] <= a[j]){
temp[k++] = a[i++];
}else{
temp[k++] = a[j++];
}
}
while(i <= mid){
temp[k++] = a[i++];
}
while(j <= end){
temp[k++] = a[j++];
}
for(i = 0;i < k;i++){
a[i+start] = temp[i];
}
}
}
2、快速排序
思想:分治策略
基本动作:“交换”
基本过程(分治三步骤):
1)分解:以a[q]为基准元,将a[p….r]经过一系列的变换分成三段,a[p,q-1],a[q],a[q+1,r]
2)递归:对a[p,q-1]和a[q+1,r]进行递归排序
3)合并:不需要此步骤,过程中已经排好
时间复杂度:最好O和平均为(nlogn),最坏为O(n²),其运行时间与划分是否对称有关,与交换次数无关。
实现(随机快排):
参考了blog:https://blog.csdn.net/MoreWindows/article/details/6684558
public class QuickSort {
/**
* 划分主体
* @param a
* @param l
* @param r
* @return
*/
public int partition(int[] a,int l,int r) {
// 生成一个随机下标,随机选择基准元,可期望划分是比较对称的。
int k = getRandomIndex(l,r);
// 这里一定要swap,否则每一次递归生成的k都不一样,会导致结果错误
swap(a,l,k);
int i = l, j = r, x = a[l];
while (i < j) {
while (i < j && a[j] >= x) {
j--;
}
if (i < j) {
a[i] = a[j];
}
while (i < j && a[i] < x) {
i++;
}
if (i < j) {
a[j] = a[i];
}
}
a[i] = x;
return i;
}
/**
* 快排主体
* @param a
* @param l
* @param r
*/
public void quickSort(int[] a,int l,int r){
if(l < r){
int i = partition(a,l,r);
quickSort(a,l,i-1);
quickSort(a,i+1,r);
}
}
public int getRandomIndex(int l,int r){
return new Random().nextInt(r-l+1) + l;
}
public void swap(int[] a,int i,int j){
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}