从列表中查找具有最小XOR值的对

时间:2012-03-01 21:59:36

标签: algorithm data-structures

我正在研究一个问题,在这个问题上我应该采用xor 数组中的所有整数对,然后找到K最小的 xor'ing生成的整数。阵列的大小可以是N = 100000 因此K可能非常大但仅限于250000。

例如, 如果N = 5且K = 4,

我们的数组是{1 3 2 4 2}

xoring(1和3,1-2,1-4,1-2,3-2,3-4,3-2等)产生的数字

3 3 2 5 0 1 6 1 6 7

由于K = 4,我们必须打印4个最小的整数。 所以答案是0 1 1 2。

由于时间限制为2秒且非常紧,使用蛮力方法 xoring所有数字都会超时。我的做法是错误的,所以我需要 救命。可能是我们可以利用K = 250000的限制,并想知道它是否 可以得到K个最小的数字,而不用整理所有整数。

3 个答案:

答案 0 :(得分:5)

(x ^ y) == (x | y) - (x & y) >= |y - x|

按顺序对数字进行排序将是一个开始,因为这些对之间的差异将为您提供xor的下限,因此是何时停止寻找数字xor x的截止点。

还有一条快捷方式可以查找xor小于(例如)2的幂的数字对,因为您只对x< = y< = x |感兴趣(2 ^ N - 1)。如果这没有给你足够的配对,请增加N并再试一次。

编辑:您当然可以通过使用x |排除已经找到的xor小于之前2的幂的数字对。 (2 ^(N-1)-1)< y< = x | (2 ^ N) - 1。

基于(已排序)[1,2,2,3,4]

的示例

首先查找xor小于1的数字对:对于每个数字x,搜索后续数字y = x。这给出了{2,2}。

如果您需要多对,请查找xor小于2但不小于1的数字对:对于每个数字x,搜索数字x< y< = x | 1.这给出了{2,3}(两次)。

请注意,最终的xor值并未完全排序,但每个批次都严格小于上一批次。

如果您需要更多,请查找xor小于4但不小于2的数字对:对于每个数字x,搜索数字x | 1< y< = x |这给出了{1,2}(两次); {1,3}。

如果您需要更多,请查找xor小于8但不小于4的数字对:对于每个数字x,搜索数字x | 3< y< = x |这给出了{1,4}; {2,4}(两次); {3,4}。

答案 1 :(得分:3)

请注意,如果数字bit nx的{​​{1}}(从右侧开始)左侧的所有位相等,则y≤2 ñ -1

x = 0000000000100110
y = 0000000000110010
               ^Everything to the left of bit 5 is equal
                so x xor y ≤ 25-1 = 31

这可以通过将每个数字存储在bitwise-trie中来利用 - 也就是说,每个边都是x xor y0的特里。然后1≤2 d(x,y) -1,其中x xor y是我们需要向上移动以找到{{的最小共同祖先'的步数1}}和d(x,y)

                             root
                        (left-most bit)
                              0
                             /
                            0
                           /
                          ...
                          1
                         / \
                        0   1
                       /   /
                      0   0
                    ... ...
                    /   /
                   0   0
                   x   y

x and y share an ancestor-node that is 5 levels up, so d(x,y) is 5

一旦你拥有了trie,很容易找到所有对x - 只需导航到叶子上方1级的所有节点,并将每个节点的子节点相互比较。这些值将为您提供最大y 2 1 -1 = 1。

如果您仍然没有d(x,y) = 1值,则向上移动到叶子上方2级的所有节点,并将每个节点的孙子彼此进行比较。这些值将为您提供最大x xor y 2 2 -1 = 3。

(实际上,您只需将左子树中的每个叶子与右子树中的每个叶子进行比较,因为给定了每个叶子中的每个叶子子树已经相互比较了)

继续此操作,直到检查给定级别的所有节点后,您的k值至少为x xor y。然后对该值列表进行排序,并取k最小值。


x xor y很小(<< n 2 )时,此算法 O(n)。对于大k,它是 O(2 b n),其中 b 是每个整数的位数 (假设重复次数不多)

答案 2 :(得分:0)

我会首先对整数的输入数组进行排序。然后,具有最小xor值的对将彼此相邻(但不是所有相邻对将具有最小的xor值)。您可以从相邻的对开始,然后向外工作,检查对(N,N + 2),(N,N + 3),直到达到所需的K个最小结果列表。

对于样本数组{1 3 2 4 2},排序数组为{1 2 2 3 4},成对xor值为:

1 xor 2 = 3
2 xor 2 = 0
2 xor 3 = 1
3 xor 4 = 7

下一步,

1 xor 2 = 3
2 xor 3 = 1
2 xor 4 = 6

再次,

1 xor 3 = 2
2 xor 4 = 6

最后,

1 xor 4 = 5

这个想法并不完整,但您应该能够使用它来帮助构建完整的解决方案。