2.5.19 #
解答 #
官方解答: Kendall Tau:https://algs4.cs.princeton.edu/25applications/KendallTau.java.html
Inversion:https://algs4.cs.princeton.edu/22mergesort/Inversions.java.html
由书中 2.5.3.2 节得,两个数组之间的 Kendall Tau 距离即为两数组之间顺序不同的数对数目。
如果能够把其中一个数组变成标准排列(即 1,2,3,4...
这样的数组),
那么此时 Kendall Tau 距离就等于另一个数组中的逆序对数量。
现在我们来解决如何把一个数组 a
变成标准排列的方法。
也就是找到函数 $ f(x) $,使得 $ f(a[i])=i $ ,这样的函数其实就是数组 a
的逆数组。
如下图所示,逆数组 ainv
即为满足 ainv[a[i]] = i
的数组。
获得逆数组之后,对另一个数组 b
做同样的变换,令数组 bnew[i] = ainv[b[i]]
。
即 ainv[a[i]] = i, ainv[b[i]] = bnew[i]
。
于是问题转化为了 bnew
和标准排列之间的 Kendall Tau 距离,即 bnew
的逆序对数量。
逆序对数量的求法见 2-2-19。
代码 #
int[] testA = { 0, 3, 1, 6, 2, 5, 4 };
int[] testB = { 1, 0, 3, 6, 4, 2, 5 };
Console.WriteLine(Distance(testA, testB));
static long Distance(int[] a, int[] b)
{
if (a.Length != b.Length)
throw new ArgumentException("Array dimensions disagree");
var n = a.Length;
var ainv = new int[n];
for (var i = 0; i < n; i++)
{
ainv[a[i]] = i;
}
var bnew = new int[n];
for (var i = 0; i < n; i++)
{
bnew[i] = ainv[b[i]];
}
var inversions = new Inversions();
inversions.Count(bnew);
return inversions.Counter;
}