剑指offer-第五章优化时间和空间效率(数组中的逆序对的总数)
题目:在数组中如果两个数字的前面的数比后面的数大,则称为一对逆序对。输入一个数组求出数组中逆序对的总数。
以空间换时间:
思路:借助一个辅助数组,将原来的数组复制到该数组中。然后将该数组分成子数组,然后统计子数组中内部的逆序,然后再统计两个相连的子数组中的逆序对,这个过程用到了归并排序。时间复杂度为O(nlogn)。
如下图所示:
Java代码:
public class ReversePairs { public int reversePairs(int[] a){ if(a==null) return 0; int[] b=new int[a.length]; System.arraycopy(a, 0, b, 0, a.length); int count=reversePairsCore(a,b,0,a.length-1); return count; } public int reversePairsCore(int[] a, int[] b, int start, int end) { if(a==null||b==null) return 0; if(start==end){ b[start]=a[start]; return 0; } int len=(end-start)/2; int left=reversePairsCore(b,a,start,start+len); int right=reversePairsCore(b,a,start+len+1,end); //初始化前半段的最后一个数字的下标 int i=start+len; //初始化后半段的最后一个数字的下标 int j=end; //初始化复制数组的最后一个数字的下标 int copyIndex=end; int count=0; while(i>=start&&j>=start+len+1){ if(a[i]>a[j]){ b[copyIndex--]=a[i--]; count+=j-start-len; } else b[copyIndex--]=b[j--]; } for(;i>=start;i--){ b[copyIndex--]=a[i]; } for(;j>=start+len+1;j--) b[copyIndex--]=a[j]; return left+right+count; } public static void main(String[] args){ int[] a={7,5,6,4}; ReversePairs rp=new ReversePairs(); int count=rp.reversePairs(a); System.out.println(count+" "); } }