算法导论学习1--分治法计算逆序数

来源:互联网 发布:网店运维 s5源码下载 编辑:程序博客网 时间:2024/06/15 14:15

 闲来无事,复习复习经典的算法导论。看到了2-4,习题,计算逆序数的问题,忍不住实现了一下。

 

逆序数,是排列组合中常见的一个指标,可以用来衡量一个数列的杂乱成对(相对于顺序排列),在一些算法如水印算法中有广泛的应用。 如此如何快速的求得任意序列的逆

序数是关心的重点。常见的一种高效解法,是devid - and -conqure. 将序列平分成两段,分别计算逆序数,然后将两个有序的数列进行归并,并在归并过程中求取逆序数。两个

子序列的逆序数求取是较小规模的同样问题,可以用递归的方式完成。

 

简单说下如何在归并的过程中,计算逆序数。假设,有一个序列array[p, mid, r]. 其中array[p...mid], array[mid+1, ..., r]已经分别从小到大排好序。下面我们将两个子序列进行归

并。  假设当前的右边子序列(array[mid+1, ...., r])的当前待比较元素下表为right, 左边的为left, 当array[left] <= array[right], 这时候没有逆序发生(因为left的数 比right的

大)。当array[left] > array[right], 是,right指向的元素具有逆序数,个数为他之前的所有的数,即mid-left+1。如此遍历下去,即可得到在归并中得到逆序数。

 

算法非常简单直白。 复杂度为: T(n) = 2T(n/2) + O(n).  根据master定理, T(n) = O(nlogn). 空间复杂度为2n,当然可以更小,2logn。

 

附上java实现的源代码。

 

public class MergInversionCount {public static int count(int[] array, int p, int r) {int inversionCount = 0;if (p < r) {int mid = (p + r) / 2;inversionCount += count(array, p, mid);inversionCount += count(array, mid+1, r);inversionCount += mergeInversion(array, p, mid, r);}return inversionCount;}private static int mergeInversion(int[] array, int p, int mid, int r) {int inversionCount = 0;int[] temp = new int[r-p+1];if(array.length < r)return inversionCount;int left = p;int right = mid + 1;int storeIndex = 0;while(left <= mid && right <= r){if(array[left] > array[right]){inversionCount += mid-left+1; //当前right存在逆序数,数目等于mid-left+1temp[storeIndex] = array[right];right++;}else{temp[storeIndex] = array[left];left++;}storeIndex++;}if(left <= mid){for(int i = left; i <= mid; i++){temp[storeIndex] = array[i];storeIndex++;}}if(right <= r){for(int i = right; i <= r; i++){temp[storeIndex] = array[i];storeIndex++;}}for(int i = p; i <= r; i++){array[i] = temp[i-p];}return inversionCount;}}import static org.junit.Assert.*;import org.junit.Test;public class MergInversionCountTest {@Testpublic void testCount() {int[] array = {1,5,6,7,4};int[] array2 = {1,5,6,7,4,3,11, 15, 13, 2, 8};int inversionCount = MergInversionCount.count(array, 0, 4);assertTrue(inversionCount == 3 );inversionCount = MergInversionCount.count(array2, 4, 10);assertTrue(inversionCount == 10 );}}


 

 

 

原创粉丝点击