归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法,归并排序对序列的元素进行逐层折半分组,然后从最小分组开始比较排序,合并成一个大的分组,逐层进行,最终所有的元素都是有序的。
我们有一个方法f(int[] arr,int L,int R]
他能将数组arr的L到R范围内变为有序数组
假设一个数组:arr[5,2,3,6,5,0]
即f(int[] arr,int L,int M] 和 f(int[] arr,int M+1,int R]
即 [2,3,5,0,5,6]
具体过程如下:
public class MergeSort {
public static void main(String[] args) {
int[] arr= {1,6,4,5,9,2};
int len=arr.length;
process(arr, 0, len-1);
// noRecursion(arr);
for(int i=0;i<len;i++) {
System.out.print(arr[i]+" ");
}
}
//递归
public static void process(int[] arr,int L,int R) {
if(L==R) {
return;
}
int mid=L+((R-L)>>1);
process(arr, L, mid);
process(arr,mid+1, R);
merge(arr, L, mid, R);
}
//非递归
public static void noRecursion(int[] arr) {
int len=arr.length;f
if(arr==null||len<2) {
return;
}
int mergeSize=1; //当前有序的左长度
while(mergeSize<len) {
int l=0;
while(l < len) { //l...m左组
int m=l+mergeSize-1;
if(m>=len) {
break;
}
int r=Math.min(len-1, m+mergeSize);
merge(arr, l, m, r);
l=r+1;
}
if(mergeSize>len/2) { //防止溢出
break;
}
mergeSize <<= 1; //mergeSize乘2,位运算赛高
}
}
public static void 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;
while(p1<=M&&p2<=R) {
help[i++]=arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
}
//处理还未放入help的元素
while(p1<=M) {
help[i++]=arr[p1++];
}
while(p2<=R) {
help[i++]=arr[p2++];
}
//赋值给arr
i=0;
for(int j:help) {
arr[L+i++]=j;
}
}
}
归并排序算法每次将序列折半分组,共需要logn轮,因此归并排序算法的时间复杂度是O(nlogn)
归并排序算法排序过程中需要额外的一个序列去存储排序后的结果,所占空间是n,因此空间复杂度为O(n)
归并排序算法在排序过程中,相同元素的前后顺序并没有改变,所以归并排序是一种稳定排序算法
在一个数组中,一个数左边比它小的数的和为这个数的小和,所有数的小和加起来叫做这个数组的小和。求数组小和
例子:
我们可以利用merge之前左右两边数组的有序性来简化判断
代码如下:
//求小和
public class SmallSum {
public static void main(String[] args) {
int[] arr= {1,3,4,2,5};
System.out.println(process(arr, 0, arr.length-1));
}
public static int process(int[] arr,int l,int r) {
if(l==r) {
return 0;
}
int mid=l+((r-l)>>1);
return process(arr, l, mid)
+process(arr, mid+1, r)
+merge(arr, l, mid, r);
}
public static int merge(int[] arr,int l,int m,int r) {
int[] help=new int[r-l+1];
int p1=l;
int p2=m+1;
int res=0;
int i=0;
while(p1<=m&&p2<=r) {
//如果arr[p1]
res+=arr[p1]<arr[p2]?arr[p1]*(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++];
}
return res;
}
}
参考博文:https://blog.csdn.net/qq_35344198/article/details/106857042