Algorithm 计算两个整数序列间Kendall-Tau距离的快速算法
我得到两个长度相等的整数序列,例如 3 1 2 5 4 532114 我想找出两个序列之间的Kendall-Tau距离,也就是序列之间的反向对数。例如,我们在第一个序列中有(3,5)(3在5之前),在第二个序列中有(5,3)。我做了一个快速的O(n^2)算法来检查这个数字,但是对于长度为40000或更大的序列来说,它的计算量太大了。我读过,我可以在做冒泡排序时计算倒数,将第一个序列转换成第二个序列,但这又是O(n^2)Algorithm 计算两个整数序列间Kendall-Tau距离的快速算法,algorithm,Algorithm,我得到两个长度相等的整数序列,例如 3 1 2 5 4 532114 我想找出两个序列之间的Kendall-Tau距离,也就是序列之间的反向对数。例如,我们在第一个序列中有(3,5)(3在5之前),在第二个序列中有(5,3)。我做了一个快速的O(n^2)算法来检查这个数字,但是对于长度为40000或更大的序列来说,它的计算量太大了。我读过,我可以在做冒泡排序时计算倒数,将第一个序列转换成第二个序列,但这又是O(n^2) 无符号短n,第一个[50001],第二个[50001],s; 整数和=0;
无符号短n,第一个[50001],第二个[50001],s;
整数和=0;
cin>>n;
对于(int i=1;i>first[i];
}
//在第二个数组中,将序列中的实际条目与其索引交换
//这样我们就可以快速检查一对是否颠倒
对于(int i=1;i>s
第二[s]=i;
}
对于(int i=1;i=second[first[j]])sum++;
}
这个问题似乎与数组中的反转计数问题密切相关,不同之处在于,在这种情况下,反转意味着“元素相对于其他序列交换”,而不是“元素无序”。因为存在一个很好的O(n log n)-计算反演的时间算法,似乎有理由尝试找到一种方法来调整该算法以解决这个特殊问题
用于计数反转的分治算法基于mergesort,并假设给定序列中的任意两个元素,有一种快速(O(1)-时间)的方法来比较它们,看看它们是否在正确的顺序中。如果我们能找到一种方法,以某种方式注释第二个序列的元素,以便在时间O(1)中我们可以确定序列中的任何一对元素是有序的还是无序的,然后我们可以运行快速计数反转算法来得到你想要的答案
这里有一种方法可以做到这一点。创建一些辅助数据结构(例如,平衡的BST),将第一个数组的元素与其在第一个数组中的索引相关联。然后,复制第二个数组,将每个元素及其在第一个数组中的对应位置注释。这总共需要时间O(n log n)。然后,运行标准的O(n logn)-时间算法来计算第二个数组中的反转数,除了在比较元素时,通过它们的关联索引而不是它们的值进行比较。这总共需要时间O(n logn)完成。这就解决了问题,多亏了一点,因为您似乎在关注代码而不是算法,所以我将这个问题迁移到堆栈溢出。
unsigned short n, first[50001], second[50001], s;
int sum = 0;
cin >> n;
for(int i=1; i<n+1; i++){
cin >> first[i];
}
// in the second array exchange the actual entries in the sequence with their indices
// that way we can quickly check if a pair is inverted
for(int i=1; i<n+1; i++){
cin >> s
second[s]=i;
}
for(int i=1; i<n+1; i++){
for (int j = i+1; j < n+1; j++)
// i < j always
// when we check the indices of the respective entries in the second array
// the relationship should stay otherwise we have an inversion
if(second[first[i]]>=second[first[j]])sum++;
}