# 归并排序

## 治( •̀ ω •́ )y

(⊙﹏⊙)首先我们可以假设两个指针，p1,p2以及一个长度为两个有序数组之和的新数组。然后让他们分别指在这两个数组的第一个。好啦，我们的准备工作就做好啦~接下来我们就去比较p1 p2的大小，将小的那个数字放入到我们的新数组中，然后将指向这个数的指针后移一位，继续比较。一直重复重复，当有一个指针走完了整个数组，就将另一个数组剩下的全部放入到我们的新数组。嘻嘻，这样我们是不是就可以把两个有序数组合并成了一个新的有序数组呢( •̀ ω •́ )y。接下来看看一个很丑的图解！

## code

public class MergeSort {

public static void mergeSort(int[] a){
if (a==null||a.length<2){
return;
}
mergeSort(a,0,a.length-1);
}
public static void mergeSort(int[] a,int l,int r){
if (l == r){
return;
}
int mid = l+((r-l)/2);
mergeSort(a,l,mid);
mergeSort(a,mid+1,r);
merge(a,l,r,mid);
}

private static void merge(int []a,int l,int r,int mid) {
int[] help = new int[r-l+1];
int i = 0;
int p1 = l;
int p2 = mid +1;
while(p1 <= mid && p2 <= r){
help[i++] = a[p1] < a[p2]? a[p1++] :a[p2++];
}
while(p1 <= mid){
help[i++] = a[p1++];
}
while(p2 <= r){
help[i++] = a[p2++];
}
for (int j = 0; j < help.length; j++) {
a[l+j] = help[j];
}
}
public static void main(String[] args) {
int[] a = {1,2,3,4,6,5,2,4,5,4};
mergeSort(a);
for (int i : a) {
System.out.print(i);
}
}

}


## 小和问题

while(p1 <= mid && p2 <= r){
sum += a[p1] < a[p2]? a[p1]*(r-p2+1):0;
help[i++] = a[p1] < a[p2]? a[p1++] :a[p2++];
}

## 逆序对问题

public class MergeSort {

public static int mergeSort(int[] a){
if (a==null||a.length<2){
return 0;
}
return mergeSort(a,0,a.length-1);
}
public static int mergeSort(int[] a,int l,int r){
if (l == r){
return 0;
}
int mid = l+((r-l)/2);
return mergeSort(a,l,mid)+mergeSort(a,mid+1,r)+merge(a,l,r,mid);
}

private static int merge(int []a,int l,int r,int mid) {
int[] help = new int[r-l+1];
int i = 0;
int p1 = l;
int p2 = mid +1;
int sum = 0;
while(p1 <= mid && p2 <= r){
sum += a[p1] > a[p2]? (mid - p1 + 1):0;
help[i++] = a[p1] < a[p2]? a[p1++] :a[p2++];
}
while(p1 <= mid){
help[i++] = a[p1++];
}
while(p2 <= r){
help[i++] = a[p2++];
}
for (int j = 0; j < help.length; j++) {
a[l+j] = help[j];
}
return sum;
}
public static void main(String[] args) {
int[] a = {4,3,8,1};
System.out.print(mergeSort(a));
}

}