我想我有一个O(n lg U) 算法,其中U 是最大的数字。这个想法类似于 user949300 的想法,但更详细一些。
直觉如下。当您对两个数字进行异或运算时,要获得最大值,您希望在可能的最高位置有一个1,然后在这个位置有一个1 的配对中,您需要一个配对1 在下一个可能的最高位置,等等。
所以算法如下。首先在数字中的任意位置找到最高的1 位(您可以通过对每个n 数字执行O(lg U) 来及时做到这一点O(n lg U))。现在,将数组分成两部分 - 一个在该位中具有 1 的数字和在该位中具有 0 的组。任何最佳解决方案都必须将第一个位置的带有1 的数字与该位置的带有0 的数字组合起来,因为这会使1 位尽可能高。任何其他配对都有一个0。
现在,我们希望递归地从1 和0 组中找到具有最高1 的数字对。为此,将这两组分为四组:
- 以
11 开头的数字
- 以
10 开头的数字
- 以
01 开头的数字
- 以
00 开头的数字
如果11 和00 组或10 和01 组中有任何数字,它们的异或将是理想的(以11 开头)。因此,如果这些组对中的任何一个不为空,则从这些组递归计算理想解决方案,然后返回这些子问题解决方案的最大值。否则,如果两个组都是空的,这意味着所有数字的第二个位置必须具有相同的数字。因此,以1 开头的数字和以0 开头的数字的最佳异或最终会抵消下一个第二位,所以我们应该只看第三位。
这给出了以下递归算法,从由 MSB 划分的两组数字开始,给出答案:
- 给定组
1 和组0 以及位索引i:
- 如果位索引等于位数,则返回
1 组中的(唯一)数与 0 组中的(唯一)数的异或。
- 从这些组中构造组
11、10、01 和 00。
- 如果组
11 和组00 不为空,则递归查找从位i + 1 开始的这两个组的最大异或。
- 如果组
10 和组01 不为空,则递归查找这两个组的最大异或,从位i + 1 开始。
- 如果上述任一配对是可能的,则返回递归找到的最大配对。
- 否则,所有数字在
i 位置必须具有相同的位,因此返回通过查看组1 和0 上的位i + 1 找到的最大对。
要开始该算法,您实际上可以将初始组中的数字分成两组 - MSB 1 的数字和 MSB 0 的数字。然后,您使用两组数字对上述算法进行递归调用。
例如,考虑数字5 1 4 3 0 2。这些有表示
101 001 100 011 000 010
我们首先将它们分成1 组和0 组:
101 100
001 011 000 010
现在,我们应用上述算法。我们将其分为11、10、01 和 00 组:
11:
10: 101 100
01: 011 010
00: 000 001
现在,我们无法将任何11 元素与00 元素配对,因此我们只对10 和01 组进行递归。这意味着我们构建了100、101、010 和011 组:
101: 101
100: 100
011: 011
010: 010
现在我们只剩下一个元素的桶了,我们可以检查101和010(给出111)和100和011(给出@ 987654396@)。这两种方法都适用,因此我们得到最佳答案是7。
让我们考虑一下这个算法的运行时间。请注意,最大递归深度为O(lg U),因为数字中只有O(log U) 位。在树的每一层,每个数字恰好出现在一个递归调用中,并且每个递归调用确实与0 和1 组中的数字总数成正比,因为我们需要按它们的分布来分配它们位。因此,递归树中有O(log U) 个层级,每个层级都做O(n) 的工作,总工作量为O(n log U)。
希望这会有所帮助!这是一个很棒的问题!