package 分治;
/**
* @ClassName 求排列的逆序数
* @Author ACER
* @Description
* 对于261数组,有逆序数(6,1)
* 给定一个数组 求其
* 逆序数
* @Date 2021/7/11 10:25
* @Version 1.0
**/
public class 求排列的逆序数 {
public static void main(String[] args) {
int array[]={2,6,3,4,5,1};
System.out.println(count(array, 0, array.length-1));
}
public static int count(int[] array, int start, int end){
//先求出左右两边逆序数
//再求出左右两边加起来求逆序数
if (start<end){
int mid=start+(end-start)/2;
int cleft = count(array, start, mid);
int cright = count(array, mid+1, end);
//对左右两边排序
mergeSort(array,start,mid);
mergeSort(array,mid+1,end);
//扫描一遍数组 计算合并之后的逆序数
int mergeCount = scan(array, start, end);
return cleft+cright+mergeCount;
}else {
return 0;
}
}
//扫描一次算出左右两边合并之后的逆序数
//思路:在左右两边开始位置放置一个指针
//当左边的大于右边数时 计算出逆序数,右边数组指针以后的所有数都小于左边
//否则左边的指针后移,直到小于右边的数 当指针直到mid时退出。
private static int scan(int []array,int start,int end){
//数组已经排好序
//{3,2,1,3,2,1}
int i=start;
int mid=start+(end-start)/2;
int j=mid;
int mergecnt=0;
while(i<mid&&j<end){
if (array[i]>array[j]){
mergecnt+=end-j;
i++;
}else {
j++;
}
}
return mergecnt;
}
public static void mergeSort(int []array,int start,int end){
if (start>=end){
return;
}
int k=array[start];
int p1=end;
int p2=start;
while(p1!=p2){
//从大到小排序
while (p1>p2&&k>=array[p1]){
p1--;
}
int temp;
temp=array[p1];
array[p1]=k;
array[p2]=temp;
while (p1>p2&&array[p2]>=k){
p2++;
}
temp=array[p2];
array[p2]=k;
array[p1]=temp;
}
mergeSort(array,start,p1-1);
mergeSort(array,p1+1,end);
}
}
初学算法之分治---求逆序数
最新推荐文章于 2022-11-07 15:12:24 发布