归并排序
归并排序是我们最常使用的排序算法之一,作用是将两个或两个以上的有序数组合并成为一个新的数组,主要使用的是分治和递归的思想;
步骤
将数组分为等长的两部分,然后合并成一个新的数组,照这个思想对两半部分分别进行递归,即可;
代码
/**
* @Author: Taoyongpan
* @Date: Created in 10:11 2018/3/27
*/
public class InversePairsMain {
private static int count = 0;
public static void main(String[] args){
int[] arr = {1,2,3,4,5,6,7,0};
// System.out.println(InversePairs(arr));
InversePairs(arr);
for (int i = 0 ; i< arr.length;i++)
System.out.println(arr[i]);
}
public static void InversePairs(int [] arr) {
if (arr==null||arr.length<1){
return;
}
mergeSort(arr,0,arr.length-1);
// return count%1000000007;
}
public static void mergeSort(int[] arr,int left,int right){
if (left >= right){
return;
}
int mid = left+((right-left)>>1);
mergeSort(arr,left,mid);
mergeSort(arr,mid+1,right);
merge(arr,left,right,mid);
}
public static void merge(int[] arr,int left,int right,int mid){
int[] temp = new int[right-left+1];
int i = left;
int j = mid+1;
int n = 0;
while (i<=mid&&j<=right){
if (arr[i]<=arr[j]){
temp[n++] = arr[i++];
}else {
// count+=mid+1-i;
temp[n++] = arr[j++];
}
}
while (i<=mid){
temp[n++] = arr[i++];
}
while (j<=right){
// count+=mid+1-i;
temp[n++] = arr[j++];
// if (count>=1000000007)
// count%=1000000007;
}
for (int t = 0 ; t < temp.length;t++){
arr[left+t] = temp[t];
}
}
}
归并排序的用途
使用归并排序可以求逆数对问题;直接上代码,根据代码讲解问题:
/**
* @Author: Taoyongpan
* @Date: Created in 10:11 2018/3/27
*/
public class InversePairsMain {
private static int count = 0;
public static void main(String[] args){
int[] arr = {1,2,3,4,5,6,7,0};
System.out.println(InversePairs(arr));
}
public static int InversePairs(int [] arr) {
if (arr==null||arr.length<1){
return 0;
}
mergeSort(arr,0,arr.length-1);
return count;
}
public static void mergeSort(int[] arr,int left,int right){
if (left >= right){
return;
}
int mid = left+((right-left)>>1);
mergeSort(arr,left,mid);
mergeSort(arr,mid+1,right);
merge(arr,left,right,mid);
}
public static void merge(int[] arr,int left,int right,int mid){
int[] temp = new int[right-left+1];
int i = left;
int j = mid+1;
int n = 0;
while (i<=mid&&j<=right){
if (arr[i]<=arr[j]){
temp[n++] = arr[i++];
}else {
count+=mid+1-i;
temp[n++] = arr[j++];
}
}
while (i<=mid){
temp[n++] = arr[i++];
}
while (j<=right){
count+=mid+1-i;
temp[n++] = arr[j++];
}
for (int t = 0 ; t < temp.length;t++){
arr[left+t] = temp[t];
}
}
}
我们求逆数对个数的时候,知识在两个有序数组合并的过程中,当arr[i]>arr[j]的时候会产生逆数对,此时说明,这个有序数组从i位置开始后面的数都大于arr[j],此时产生mid-i+1个逆数对,当数组合并完成的时候,就能统计出整个数组包含的逆数对个数;