【题目】在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
* 【思路】运用归并排序的思想。
* 首先将数组分成两个子数组,统计子数组的逆序对;
* 再合并,统计整个的逆序对。
1 package com.exe11.offer; 2 3 /** 4 * 【题目】在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。 5 * 【思路】运用归并排序的思想。 6 * 首先将数组分成两个子数组,统计子数组的逆序对; 7 * 再合并,统计整个的逆序对。 8 * @author WGS 9 * 10 */ 11 public class InversePairsCount { 12 public int InversePairs(int[] data){ 13 if(data==null ||data.length<=0) 14 return 0; 15 int[] copy=new int[data.length]; 16 for(int i=0;i<data.length;i++){ 17 copy[i]=data[i]; 18 } 19 int count=InversePairsCountCore(data,copy,0,data.length-1); 20 return count; 21 } 22 23 private int InversePairsCountCore(int[] data, int[] copy, int start, int end) { 24 if(start==end){ 25 copy[start]=data[start]; 26 return 0; 27 } 28 //分成两个子数组 29 int len=(end-start)/2; 30 int leftCount=InversePairsCountCore(copy,data,start,start+len);//然后使用递归对左数组不断进行分解,直至start==end,即只有一个数的情况 31 int rightCount=InversePairsCountCore(copy,data,start+len+1,end); 32 33 int i=start+len;//左数组最后一个数下标 34 int j=end; 35 int indexOfCopy=end;//在数组copy中,从最后一位进行复制 36 int count=0; 37 while(i>=start && j>=start+len+1){ 38 if(data[i]>data[j]){//如果左数组最后一个数大于右数组最后一个数,逆序对数为右数组剩下数字的个数,并将左数组此数组添加至copy数组中 39 copy[indexOfCopy--]=data[i--]; 40 count+=j-start-len; 41 }else{ 42 copy[indexOfCopy--]=data[j--]; 43 } 44 } 45 for(;i>=start;i--) 46 copy[indexOfCopy--]=data[i]; 47 for(;j>=start+len+1;j--) 48 copy[indexOfCopy--]=data[j]; 49 50 51 return leftCount+rightCount+count; 52 } 53 54 public static void main(String[] args) { 55 InversePairsCount i=new InversePairsCount(); 56 int[] nums=new int[]{7,5,6,4}; 57 int n=i.InversePairs(nums); 58 System.out.println(n); 59 60 } 61 }