一、归并排序
①先将数组分成两半,再分别将左边排好序,右边排好序。
②然后申请一个辅助数组,用两个标志指向左右数组的第一个元素。
③首先两个头元素对比,较小的归入辅助数组,然后将指标往后移,较大的不动,继续比较。
④当一边数组完全归入辅助数组后,因为数组是有序的,另一个数组剩下的元素直接归入辅助数组。
⑤最后将辅助数组copy回原数组,就排好序了。
时间复杂度O(N*logN),额外空间复杂度O(N)
public mergeSort(int[] arr){
if(arr == null || arr.length < 2){
return;
}
sortProcess(arr, 0, arr.length-1);
}
public static void sortProcess(int[] arr, int L, int R){
if(L == R){
return;
}
int mid = L+(R-L)/2;
sortProcess(arr, L, mid);
sortProcess(arr, mid+1, R);
merge(arr, L, mid, R);
}
public static void merge(int[] arr, int L, int mid, int R){
int[] help = new int[R-L+1];
int i = 0;
int p1 = L;
int p2 = mid+1;
while(p1 <= mid && p2 <= R){
help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
while(p1 <= mid){
help[i++] = arr[p1++];
}
while(P2 <= R){
help[i++] = arr[p2++];
}
for(i = 0; i < help.length; i++){
arr[L+i] = help[i];
}
}
二、小和问题
求给定所以数的左边小于其自身的数的和
换一个角度想:就是所有大于k的数的小和里都会有k
public static int smallSum(int[] arr){
if(arr = null || arr.length < 2){
return 0;
}
return mergeSort(arr, 0, arr.length-1);
}
public static int mergeSort(int[] arr, int l, int r){
if(l == r){
return 0;
}
int mid = L + (R-L)/2;
return mergeSort(arr, l, mid)
+ mergeSort(arr, mid+1, r)
+ merge(arr. l, r);
}
public static int merge(int[] arr, int l, int m, int r){
int[] help = new int[r-l+1];
int i = 0;
int p1 = l;
int p2 = m+1;
int res = 0;
while(p1 <= m && p2 <= r){
res += arr[p1] < arr[p2] ? (r-p2+1)*arr[p1] : 0;
help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
while(p1 <= m){
help[i++] = arr[p1++];
}
while(p2 <= r){
help[i++] = arr[p2++];
}
for(i = 0; i < help.length; i++){
arr[l+i] = help[i];
}
return res;
}
三、逆序对问题
如果数组中任意一个数的左边的数比它大,就构成了一对逆序对,求打印逆序对个数。
换一个角度想就是求一个数右边有多少个数比它小
public static int backWard(int[] arr){
if(arr = null || arr.length < 2){
return 0;
}
return mergeSort(arr, 0, arr.length-1);
}
public static int mergeSort(int[] arr, int l, int r){
if(l == r){
return 0;
}
int mid = L + (R-L)/2;
return mergeSort(arr, l, mid)
+ mergeSort(arr, mid+1, r)
+ merge(arr. l, r);
}
public static int merge(int[] arr, int l, int m, int r){
int[] help = new int[r-l+1];
int i = 0;
int p1 = l;
int p2 = m+1;
int res = 0;
while(p1 <= m && p2 <= r){
res += arr[p1] > arr[p2] ? (r-p2+1) : 0;
help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
while(p1 <= m){
help[i++] = arr[p1++];
}
while(p2 <= r){
help[i++] = arr[p2++];
}
for(i = 0; i < help.length; i++){
arr[l+i] = help[i];
}
return res;
}