algorithm – 使用BIT计算反转

我知道之前已经讨论过这个问题,但我有兴趣使用二进制索引树来做这个.我发现 this 链接显示如何做.我没有完全按照解释.有人可以请给我一个解释为什么以下给出的确实如此.

Create a BIT of size greater than n(no of elements). Iterate through array A (
let j be the index of loop),and for each element A[j] do:

1) Add j-sum(A[j]) to the number of inversions
2) add(A[j], 1) (i.e. add 1 to the position A[j] on BIT. This effectively 
counts the number of time value A[j] is seen so far)

我不明白为什么这样做.

当元素大于数组中跟随它的某个元素时,会发生反转.

我们可以通过将它们按第二个元素分组来计算反转.例如,在数组[4,3,1,2]中,元素对(4,3),(4,1),(4,2),(3,1)和(3,2)是倒置.我们用第二个元素对它们进行分组,因此:[[(4,1),(3,1)],[(4,2),(3,2)],[(4,3)]].

我们依次考虑每个元素,并计算它是第二个元素的反转次数.在该示例中,元素4是0反转中的第二元素,元素3在1中反转,并且元素1和2在2中反转.

为了使任何给定元素成为反转的第二个元素,在数组之前必须有一个更大的元素.

我们通过从左到右遍历数组来有效地执行计数,并始终使用BIT跟踪到目前为止遇到的每个值的元素数量.最初我们的频率表将是[0,0,0,0],因为我们根本没有看到任何元素.在我们访问4之后,我们更新其频率,给出[0,0,0,1].访问3后,[0,0,1,1]等等.

每次我们访问某个职位时,我们都会使用BIT来查明到目前为止访问过的元素数量是多少.因此,例如当我们遇到1时,BIT当前包含[0,0,1,1],表示到目前为止零1和2,一个3和一个4.通过添加值0 1 1,我们计算到目前为止大于1的元素数量.

添加所有这些个别计数会给出反转的总数.

请注意,通常,您必须使用坐标压缩才能使其高效.例如,如果您的初始数组包含A = [92,631,50,7]之类的数字,则不应分配包含数百个元素的BIT.相反,对数组进行排序以确定7< 50< 92< 631,这允许我们分配等级7 => 1,50 => 2,92 => 3,631 => 4;然后用它的等级替换每个元素,给出B = [3,4,2,1].由于B [i]>,因此该阵列的反转次数与原始阵列的反转次数相同. B [j]当且仅当A [i]> A [J].

(注意:真正的程序员可能会使用从零开始的索引.)

翻译自:https://stackoverflow.com/questions/11497502/counting-inversions-using-bit

转载注明原文:algorithm – 使用BIT计算反转