用divide&conquer思想解决求逆序数对的问题

来源:互联网 发布:网络主播年龄限制 编辑:程序博客网 时间:2024/05/21 06:20

对于一个给定的数组中要去求其中逆序数对的个数,可以通过简单的两层for循环去逐个便利每一个数对,这样的思想是很容易就可以想到

 

的,但是其算法的复杂度确是O(n^2),为了降低算法的复杂度可以试着用divide&conquer思想去考虑这个问题。

 

 

对于一个数组{5,3,7,4,6,2,1,8},如果我们以中间(或者左中)为界限将其分成两个数组,只要知道这两个数组中的逆序对数和两边

 

的数所组成的逆序对数就是它所有的逆序对数了。而数组划分的递归结束点在两个数组都只有一个元素的时候,因此两数组中的逆序对数可以

 

通过递归求得。要去求分裂的两数组中的逆序对数可以这样去做:先将两数组按升序排序,若前一个数组的第一个元素比后一个的大,则说

 

明前一组的后面所有都要比后一组的第一个元素大,这样将较小的第一个元素去掉后,继续比较两个数组的第一个元素可以把所有的逆序对找

 

到。

 

下面是该算法的JAVA实现:

 

 

import java.util.*;

 

public class CountInversedNumbers{

 

public static int count=0;                   //记录逆序对个数;

 

public void  sort_count(int []L){

int n=L.length;                     

int a=(int)(n/2+0.5);                

int b=(int)(n/2);

int A[]=new int[a];

int B[]=new int[b];

for (int i=0;i<a;i++) 

A[i]=L[i];

for (int j=0;j<b;j++) 

B[j]=L[j+a];                                //把单个数组划分成两个数组;

if(a>1&&b>1) {

sort_count(A);

sort_count(B);                              //递归的划分数组;

}

Arrays.sort(A);                              

Arrays.sort(B);                             //将数组排序;

 

merge_count(A,B);

 

}

 

public void merge_count(int []M, int[]N){    //求被划分的两个数组中元素组成的逆序对;

int c=M.length;

int d=N.length; 

 

while(c>0&&d>0)

{

  if(M[0]>N[0]) {

  this.count=this.count+c;

  for(int i=0;i<d-1;i++) 

  N[i]=N[i+1];

  d--;

  }

  else{

  for(int j=0;j<c-1;j++) 

  M[j]=M[j+1];

  c--;

  }

}

 

 }

    public static void main(String[] args){

int K[]={6,2,3,5,7,1,4,8};

CountInversedNumbers a=new CountInversedNumbers();

a.sort_count(K);

System.out.println(a.count);                                    //输出结果是11;

}

}