数组中异或最大的两个元素
给定一个整数数组,您必须找到异或最大的两个元素。
有一种简单的方法——只需选择每个元素并与其他元素进行异或,然后比较结果即可找到该对。
除此之外,还有什么高效的算法吗?
Given an array of integers ,You have to find two elements whose XOR is maximum.
There is naive approach --just by picking each element and xoring with other elements and then comparing the results to find the pair.
Other than this ,Is there any efficient algorithm?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
这可以使用 Trie 以
O(NlogN)
时间复杂度解决。arr[i]
元素arr[i]
可能的最大异或值。我们知道不同类型的位(0 ^ 1
或1 ^ 0
)的异或总是1
。因此,在查询每个位时,尝试遍历持有相反位的节点。这将使特定位1
导致异或值最大化。如果不存在位相反的节点,才遍历同位节点。arr[i]
插入trie中。对于
N
元素,我们需要为每个元素进行一次查询 (O(logN)
) 和一次插入 (O(logN)
)。所以总体时间复杂度是O(NlogN)
。您可以在此线程中找到有关其工作原理的精美图解说明。
下面是上述算法的 C++ 实现:
This can be solved in
O(NlogN)
time complexity using Trie.arr[i]
element ofarr[0, 1, ..... N]
arr[i]
. We know xor of different type of bits(0 ^ 1
or1 ^ 0
) is always1
. So during query for each bit, try to traverse node holding opposite bit. This will make that particular bit1
result in maximizing xor value. If there is no node with opposite bit, only then traverse the same bit node.arr[i]
into trie.For
N
elements, we need one query(O(logN)
) and one insertion(O(logN)
) for each element. So the overall time complexity isO(NlogN)
.You can find nice pictorial explanation on how it works in this thread.
Here is C++ implementation of the above algorithm:
忽略符号位,其中一个值必须是具有最高有效位设置的值之一。 除非所有值都设置了该位,在这种情况下,您将转到未在所有值中设置的下一个最高有效位。因此,您可以通过查看 HSB 来减少第一个值的可能性。例如,如果可能性是
最大对的第一个值必须是 0x100000 或 0x10ABCD。
@内部服务器错误我认为最小不一定是正确的。我没有减少第二个值的好主意。只是可能的第一个值列表中不的任何值。在我的示例中,为 0x001ABC 或 0x000ABC。
Ignoring the sign bit, one of the values must be one of the values with the highest significant bit set. Unless all the values have that bit set, in which case you go to the next highest significant bit that isn't set in all the values. So you could pare down the possibilities for the 1st value by looking at the HSB. For example, if the possibilities are
The 1st value of the max pair must be either 0x100000 or 0x10ABCD.
@internal Server Error I don't think smallest is necessarily correct. I don't have a great idea for paring down the 2nd value. Just any value that isn't in the list of possible 1st values. In my example, 0x001ABC or 0x000ABC.
一个非常有趣的问题!
这是我的想法:
表示并首先将它们排序到树中最高有效位
(添加前导零以匹配最长的数字)。完成每条路径后
从根到任意叶子都代表原来的一个数字
放。
如果 a 和 b 到达叶子,则 应该指向具有“很少”相同位的两个数字。
我刚刚提出这个算法,不知道它是否正确或如何证明它。然而它应该在 O(n) 运行时间内。
A very interesting problem!
Here is my idea:
representation and sort them into the tree most significant bit first
(add leading zeros to match the longest number). When done each path
from the root to any leaf represents one number from the original
set.
If a and b reach a leaf, the should point to two numbers with "very few" identical bits.
I just made this algorithm up and do not know if its correct or how to prove it. However it should be in O(n) running time.
创建一个递归函数,将两个整数列表 A 和 B 作为参数。作为其返回值,它返回两个整数,一个来自 A,一个来自 B,这使得两者的 XOR 最大化。如果所有整数均为 0,则返回 (0,0)。否则,该函数会进行一些处理并递归调用自身两次,但使用较小的整数。在其中一个递归调用中,它考虑从列表 A 中取出一个整数,为位 k 提供 1,而在另一个调用中,它考虑从列表 B 中取出一个整数,为位 k 提供 1。
我现在没有时间填写详细信息,但也许这足以看到答案?另外,我不确定运行时间是否会比 N^2 更好,但可能会。
Make a recursive function that takes two lists of integers, A and B, as its arguments. As its return value, it returns two integers, one from A and one from B, which maximize the XOR of the two. If all the integers are 0, return (0,0). Otherwise, the function does some processing and calls itself recursively twice, but with smaller integers. In one of the recursive calls, it considers taking an integer from list A to supply a 1 to bit k, and in the other call it considers taking an integer from list B to supply a 1 to bit k.
I don't have time now to fill in the details, but maybe this will be enough for to see the answer? Also, I'm not sure if the run time will be better than N^2, but it probably will be.
我们可以在 O(n) 时间内找到最大数,然后循环遍历数组,对每个元素进行异或。假设异或运算成本为 O(1),我们可以在 O(n) 时间内找到两个数字的最大异或。
We can find the maximum number in O(n) time then loop through the array doing xor with each element. Assuming xor operation cost is O(1) we can find max xor of two numbers in O(n) time.
我想我有一个 O(n lg U) 算法,其中 U 是最大的数字。这个想法与user949300类似,但有更多细节。
直觉如下。当您将两个数字异或在一起时,为了获得最大值,您希望在尽可能最高的位置有一个
1
,然后是具有1
的配对在这个位置,您希望与下一个可能的最高位置处的1
进行配对,依此类推。因此算法如下。首先找到数字中任意位置的最高
1
位(您可以通过执行O(lg U)
在O(n lg U)
时间内完成此操作code> 对每个n
数字起作用)。现在,将数组分成两部分 - 一个是该位中具有1
的数字,另一个是该位中具有0
的数字。任何最佳解决方案都必须将第一个位置带有1
的数字与该位置带有0
的数字组合起来,因为这样会出现1
> 尽可能高一点。任何其他配对都有0
。现在,我们希望递归地从
1
和0
组中找到1
最高的数字配对。为此,请将这两组中的它们分为四组:11
开头的数字10
01
00
如果
11
和00
组或10
和01 中有任何数字
组,他们的异或将是理想的(以11
开头)。因此,如果这些组对中的任何一个不为空,则递归地计算这些组中的理想解决方案,然后返回这些子问题解决方案中的最大值。否则,如果两组都是空的,则意味着所有数字的第二个位置必须具有相同的数字。因此,以1
开头的数字和以0
开头的数字的最佳 XOR 最终会抵消下一个第二位,因此我们应该只看第三个位少量。这给出了以下递归算法,该算法从按 MSB 划分的两组数字开始给出答案:
1
和组0
以及位索引我:- 如果位索引等于位数,则返回
- 从这些组中构造组
- 如果组
- 如果组
- 如果上述任一配对可行,则返回递归找到的最大配对。
- 否则,所有数字在位置
1
组中的(唯一)数字与0
组中的(唯一)数字的 XOR > 小组。11
、10
、01
和00
。11
和组00
非空,则从位i + 1
开始递归查找这两个组的最大异或。< /里>10
和组01
非空,则从位i + 1
开始递归查找这两个组的最大异或。i
中必须具有相同的位,因此返回通过查看组上的位
和i + 1
找到的最大对10
。要开始算法,您实际上可以将初始组中的数字分为两组 - MSB
1
的数字和 MSB0
的数字。然后,您使用两组数字对上述算法进行递归调用。例如,考虑数字
5 1 4 3 0 2
。这些具有表示形式,我们首先将它们分为
1
组和0
组:现在,我们应用上述算法。我们将其分为
11
、10
、01
和00
组:现在,我们无法将任何组配对
11
元素与00
元素,因此我们只需递归10
和01
组。这意味着我们构建100
、101
、010
和011
组:现在我们要对于只有一个元素的存储桶,我们只需检查
101
和010
(给出111
)和100
对代码> 和011
(给出111
)。任一选项在这里都有效,因此我们得到最佳答案是7
。让我们考虑一下这个算法的运行时间。请注意,最大递归深度为
O(lg U)
,因为数字中只有O(log U)
位。在树的每一层,每个数字都出现在一次递归调用中,并且每个递归调用的工作量与0
和1
中的数字总数成正比。组,因为我们需要按位分配它们。因此,递归树中有O(log U)
层,每个层的工作量为O(n)
,总工作量为O(n记录U)
。希望这有帮助!这是一个很棒的问题!
I think I have a
O(n lg U)
algorithm for this, whereU
is the largest number. The idea is similar to user949300's, but with a bit more detail.The intuition is as follows. When you're XORing two numbers together, to get the maximum value, you want to have a
1
at the highest possible position, and then of the pairings that have a1
at this position, you want a pairing with a1
at the next possible highest position, etc.So the algorithm is as follows. Begin by finding the highest
1
bit anywhere in the numbers (you can do this in timeO(n lg U)
by doingO(lg U)
work per each of then
numbers). Now, split the array into two pieces - one of the numbers that have a1
in that bit and the group with0
in that bit. Any optimal solution must combine a number with a1
in the first spot with a number with a0
in that spot, since that would put a1
bit as high as possible. Any other pairing has a0
there.Now, recursively, we want to find the pairing of numbers from the
1
and0
group that has the highest1
in them. To do this, of these two groups, split them into four groups:11
10
01
00
If there are any numbers in the
11
and00
group or in the10
and01
groups, their XOR would be ideal (starting with11
). Consequently, if either of those pairs of groups isn't empty, recursively compute the ideal solution from those groups, then return the maximum of those subproblem solutions. Otherwise, if both groups are empty, this means that all the numbers must have the same digit in their second position. Consequently, the optimal XOR of a number starting with1
and a number starting with0
will end up having the next second bit cancel out, so we should just look at the third bit.This gives the following recursive algorithm that, starting with the two groups of numbers partitioned by their MSB, gives the answer:
1
and group0
and a bit indexi
:1
group and the (unique) number in the0
group.11
,10
,01
, and00
from those groups.11
and group00
are nonempty, recursively find the maximum XOR of those two groups starting at biti + 1
.10
and group01
are nonempty, recursively find the maximum XOR of those two groups, starting at biti + 1
.i
, so return the maximum pair found by looking at biti + 1
on groups1
and0
.To start off the algorithm, you can actually just partition the numbers from the initial group into two groups - numbers with MSB
1
and numbers with MSB0
. You then fire off a recursive call to the above algorithm with the two groups of numbers.As an example, consider the numbers
5 1 4 3 0 2
. These have representationsWe begin by splitting them into the
1
group and the0
group:Now, we apply the above algorithm. We split this into groups
11
,10
,01
, and00
:Now, we can't pair any
11
elements with00
elements, so we just recurse on the10
and01
groups. This means we construct the100
,101
,010
, and011
groups:Now that we're down to buckets with just one element in them, we can just check the pairs
101
and010
(which gives111
) and100
and011
(which gives111
). Either option works here, so we get that the optimal answer is7
.Let's think about the running time of this algorithm. Notice that the maximum recursion depth is
O(lg U)
, since there are onlyO(log U)
bits in the numbers. At each level in the tree, each number appears in exactly one recursive call, and each of the recursive calls does work proportional to the total number of numbers in the0
and1
groups, because we need to distribute them by their bits. Consequently, there areO(log U)
levels in the recursion tree, and each level doesO(n)
work, giving a total work ofO(n log U)
.Hope this helps! This was an awesome problem!