(逆序对)假设A[1..n]A[1..n]A[1..n]是一个有nnn个不同数的数组。若i<ji < ji<j且A[i]>A[j]A[i] > A[j]A[i]>A[j],则对偶(i,j)(i, j)(i,j)称为A的一个逆序对(inversion)。
a. 列出数组<2,3,8,6,1><2, 3, 8, 6, 1><2,3,8,6,1>的5个逆序对。
b. 由集合1,2,…,n{1, 2, …, n}1,2,…,n中的元素构成的什么数组具有最多的逆序对?它有多少逆序对?
c. 插入排序的运行时间与输入数组中逆序对的数量之间是什么关系?证明你的回答。
d. 给出一个确定在nnn个元素的任何排列中逆序对数量的算法,最坏情况需要Θ(nlgn)Θ(n{\rm lg}n)Θ(nlgn)时间。(提示:修改归并排序)
解
a.
5个逆序对:(8,6)(6,1)(8,1)(3,1)(2,1)(8, 6) (6, 1) (8, 1) (3, 1) (2, 1)(8,6)(6,1)(8,1)(3,1)(2,1)
b.
逆序对最多的情况出现在元素按降序排列的时候,即n,n−1,…,2,1{n, n-1, … , 2, 1}n,n−1,…,2,1。这种情况下,任意两个元素都构成逆序对,一共有Cn2=(n(n−1))/2C_n^2=(n(n-1))/2Cn2=(n(n−1))/2组逆序对。
c.
插入排序的运行时间T(n)T(n)T(n)与数组中的逆序对数量R(n)R(n)R(n)成线性关系,即T(n)=Θ(R(n))T(n) = Θ(R(n))T(n)=Θ(R(n))。下面用数学归纳法证明。
初始情况n=2n = 2n=2,线性关系显然成立。
下面进入归纳过程。假设对于n−1n-1n−1个元素的情况,插入排序的运行时间T(n−1)T(n-1)T(n−1)与逆序对的数量R(n−1)R(n-1)R(n−1)成线性关系T(n−1)=Θ(R(n−1))T(n-1) = Θ(R(n-1))T(n−1)=Θ(R(n−1))。对于nnn个元素的情况,其逆序对数目R(n)R(n)R(n)分为两部分:
① 前n−1n-1n−1个元素的逆序对数目R(n−1)R(n-1)R(n−1);
② 前n−1n-1n−1个元素与第nnn个元素构成的逆序对数目Rp(n)R_p(n)Rp(n)。
故R(n)=R(n−1)+Rp(n)R(n) = R(n-1) + R_p(n)R(n)=R(n−1)+Rp(n)。
nnn个元素的插入排序可分为两步进行:
① 首先将前n−1n-1n−1个元素排序,其时间T(n−1)=Θ(R(n−1))T(n-1) = Θ(R(n-1))T(n−1)=Θ(R(n−1));
② 然后将第nnn个元素插入到已排序好的前n−1n-1n−1个元素中。前n−1n-1n−1个元素与第nnn个元素存在Rp(n)R_p(n)Rp(n)个逆序对,这说明前n−1n-1n−1个元素中一共存在Rp(n)R_p(n)Rp(n)个元素比第nnn个元素要大。插入排序在这一阶段要将第nnn个元素插入到合适的位置,这一步的运行时间Tp(n)=Θ(Rp(n))T_p(n) = Θ(R_p(n))Tp(n)=Θ(Rp(n))。
故排序nnn个元素的运行时间T(n)=T(n−1)+Tp(n)=Θ(R(n−1))+Θ(Rp(n))=Θ(R(n−1)+Rp(n))=Θ(R(n))T(n) = T(n-1) + T_p(n) = Θ(R(n-1)) + Θ(R_p(n)) = Θ(R(n-1) + R_p(n)) = Θ(R(n))T(n)=T(n−1)+Tp(n)=Θ(R(n−1))+Θ(Rp(n))=Θ(R(n−1)+Rp(n))=Θ(R(n))。
综上所述,插入排序的运行时间T(n)T(n)T(n)与数组中的逆序对数量R(n)R(n)R(n)成线性关系T(n)=Θ(R(n))T(n) = Θ(R(n))T(n)=Θ(R(n))。
d.
采用分治法。对于数组A[1..n]A[1 .. n]A[1..n],将其对半分为两个子数组:AL=A[1..⌊n/2⌋]A_L = A[1 .. ⌊n/2⌋]AL=A[1..⌊n/2⌋]和AR=A[⌊n/2⌋+1..n]A_R = A[⌊n/2⌋+1 .. n]AR=A[⌊n/2⌋+1..n]。A[1..n]A[1 .. n]A[1..n]的逆序对数目R(A)R(A)R(A)分为333部分:
① 左半边子数组ALA_LAL的逆序对数目R(AL)R(A_L)R(AL)
② 右半边子数组ARA_RAR的逆序对数目R(AR)R(A_R)R(AR)
③ 左半边子数组的元素与右半边子数组的元素构与的逆序对数目R(AL,AR)R(A_L, A_R)R(AL,AR)。
故R(A)=R(AL)+R(AR)+R(AL,AR)R(A) = R(A_L) + R(A_R) + R(A_L, A_R)R(A)=R(AL)+R(AR)+R(AL,AR)。
下面考虑③。一种简单的方法是,对ALA_LAL中的每个元素AL[i]A_L[i]AL[i],遍历ARA_RAR中的每个元素AR[j]A_R[j]AR[j],寻找与AL[i]A_L[i]AL[i]构成逆序对的元素。这种方法的时间为Θ((n/2)2)=Θ(n2)Θ((n/2)^2) = Θ(n^2)Θ((n/2)2)=Θ(n2),时间成本太高。然而,如果ALA_LAL和ARA_RAR分别已经排好序,可以把时间缩减到Θ(n)Θ(n)Θ(n)。并且,分别排序ALA_LAL和ARA_RAR并不影响ALA_LAL和ARA_RAR之间的逆序对数目R(AL,AR)R(A_L, A_R)R(AL,AR)。这一过程具体如下:

上述方法可以和归并排序揉合在一起,先执行CROSS−INVERSION−COUNT(A,p,q,r){\rm CROSS-INVERSION-COUNT}(A, p, q, r)CROSS−INVERSION−COUNT(A,p,q,r),然后执行归并排序的MERGE{\rm MERGE}MERGE过程。在递归的每一层,执行CROSS−INVERSION−COUNT(A,p,q,r){\rm CROSS-INVERSION-COUNT}(A, p, q, r)CROSS−INVERSION−COUNT(A,p,q,r)和MERGE{\rm MERGE}MERGE过程各花费Θ(n)Θ(n)Θ(n)时间。递归一共有Θ(lgn)Θ({\rm lg}n)Θ(lgn)层,因此该算法的执行时间为Θ(nlgn)Θ(n{\rm lg}n)Θ(nlgn)。下面给出完整的伪代码。

代码链接:https://github.com/yangtzhou2012/Introduction_to_Algorithms_3rd/tree/master/Chapter02/Problem_2-4/InversionCount
本文详细解释了逆序对的概念,并通过实例展示了如何找出数组中的逆序对。文章还探讨了数组中逆序对的最大数量及排列方式,并分析了逆序对数量与插入排序运行时间的关系。最后提供了一个在Θ(nlgn)时间内计算逆序对数量的算法。

2107

被折叠的 条评论
为什么被折叠?



