【问题标题】:Find the subarray with the max XOR from an array (using a trie)从数组中找到具有最大 XOR 的子数组(使用 trie)
【发布时间】:2016-08-29 19:08:25
【问题描述】:

问题陈述是:

给定一个整数数组,找到最大异或的子数组。

一些例子是:

Input: arr[] = {1, 2, 3, 4}
Output: 7
The subarray {3, 4} has maximum XOR value

Input: arr[] = {8, 1, 2, 12, 7, 6}
Output: 15
The subarray {1, 2, 12} has maximum XOR value

我找到了quora post,它提供了对问题解决方案的解释,但我不太能够完全理解所解释的内容。

文章一开始就引入了与上一个类似的问题(文章中的问题1):

给定一个整数数组,我们必须找到两个异或最大的元素

然后它描述了一个可以处理两种类型查询的 trie 数据结构:

  1. 插入一个数字 X
  2. 给定一个 Y,找出 Y 与迄今为止已插入的所有数字的最大异或。 如果我们有这个数据结构,我们将在进行过程中插入整数,并通过第二种类型的查询,我们将找到最大的 XOR

上图处理查询类型 1。对于查询类型 2,帖子有以下内容:

假设我们的数字 Y 是 b1,b2...bn,其中 b1,b2.. 是二进制位。我们从 b1 开始。现在为了使 XOR 达到最大值,我们将在进行 XOR 后尝试将最高有效位设为 1。因此,如果 b1 为 0,我们将需要 1,反之亦然。在 trie 中,我们转到所需的位边。如果没有有利的选择,我们会去另一边。对 i=1 到 n 重新执行此操作,我们将获得可能的最大 XOR。

这里有几点令人困惑。一个是:trie 究竟是如何用于找到与数组中当前点具有最大 XOR 的两个元素的?他们似乎在说这样的话:

例如 array= {1,2,3,4},当前数字是 3 -> 0011(4 位表示)意味着 1 和 2 已经插入到 trie 中。到目前为止,最大异或应该是数字 1 和 2(产生 3)。使用帖子中提供的方法,似乎可以将 max xor 存储在一个变量中,这样当数组中的最后一个数字与 trie 的当前状态进行异或时(我假设它会有元素1,2 和 3 已经插入),该变量将具有迄今为止的最大值。 但是算法如何存储已异或的两个元素以产生最大值?

最后,应该将这种方法的逻辑应用于问题(帖子中的问题2):

给定一个整数数组,找到最大异或的子数组

这里提供了以下解决方案:

假设 F(L,R) 是从 L 到 R 的子数组的 XOR。 这里我们使用 F(L,R)=F(1,R) XOR F(1,L-1) 的性质。如何? 假设我们的具有最大 XOR 的子数组在位置 i 结束。现在,我们需要最大化 F(L,i) 即。 F(1,i) XOR F(1,L-1) 其中 L

我不太了解 F(L,R)=F(1,R) XOR F(1,L-1) 的性质。我在这里假设 R 是最大子数组的右边界,而 L 是它的左边界,但不清楚为什么 F(1,i) 需要与 F(1,L -1)。由此,问题 1 的逻辑将如何应用在这里?

我意识到这个问题很长,但由于问题是多方面的,似乎有必要包括问题的这些基本部分。

【问题讨论】:

  • 为什么很难存储已异或的两个元素以产生当前最大值?只要有一个max 变量,以及arg1ToXorThatYieldsMaxarg2ToXorThatYieldsMax 变量,并在更新max 的同时更新它们。
  • 第二个问题:见this possible duplicate
  • @DanielWagner 我没有说这很难。该帖子没有提到他们如何在所描述的算法中存储这两个元素。

标签: arrays algorithm tree bit-manipulation trie


【解决方案1】:

第一个问题:当你将一个元素添加到一个 trie 时,你可以在叶子中存储额外的信息,指示该元素在数组中的索引。当您遍历特里树并到达一个使用Y 最大化异或的叶子时(如您的问题中所述),您可以记录两个索引和最大值(Y 的索引被称为您的元素即将添加)。

等式f(l, r) = f(0, r) ^ f(0, l - 1) 被证明here

一旦我们有了这个等式和第一个问题的解决方案(上面描述的稍微修改以记录索引),我们立即得到第二个问题的解决方案。如何?我们可以为所有有效的i 计算f(i),然后运行这个算法来获得两个最大化异或的索引。让他们成为LR,其中L < R。那么答案就是[L + 1, R] 子数组。

【讨论】:

  • 感谢您的链接,但我不确定我是否理解那里的最佳答案中的证明。似乎f(l,r)f(0,l-1) 都引用数组的相同元素,因此异或将返回0。但是算法中l 和r 的实际值是多少。也许一个更具体的例子将有助于展示 arr[0...l-1] 和 arr[1...r] 的值如何贯穿整个算法。
  • @loremIpsum1771 它说 f(0, l - 1) ^ f(l, r) = f(0, r) 因为 xor 操作的关联性(很明显,我们在等式两边都有从 0 到 r 的所有元素)。现在我们可以用f(0, l - 1)异或两边得到f(l, r) = f(0, r) ^ f(0, l - 1)
  • 这似乎与另一篇文章的解释基本相同(没有公认的答案)。我理解纯粹的数学等式,但不清楚它是如何应用于解决问题的。如果您可以使用一组真实的数字(例如 {1,2,3,4} 的数组)来编辑您的答案并解释算法,我可以得到更好的理解。
【解决方案2】:

从 kraskevick 的回答中可以理解数学上的相等性。

之后我们需要做的是使用包含前缀 xor 的值、指向 left(0) 和 right(1) 子节点的指针的结构将所有前缀 xor(pre_xor) 存储在 Trie 中。

这个 Trie 的所有叶节点值都将包含前缀 xor,所有非叶节点的值都为 0。

首先用 0 初始化 pre_xor 并将 0 插入到 trie 中。

然后,在获取输入后,将其与 pre_xor 进行异或运算以获取异或直到插入的最后一个元素,并将此 pre_xor 插入到 trie 中。

当我们将前缀 xor(pre_xor) 插入到第 i 个元素(它充当等式的 R,即 f(0,r))时,我们通过 trie 查询以找到 XOR 最大的合适 l即,如果 pre_xor 的最右边的数字包含 1,如果存在,我们将向 0 侧移动(如 0^1=1)。

一旦我们到达一个叶节点,我们就找到了最合适的 l,它使 Xor 最大化。这个值就是我们在给定方程中讨论的 f(0,l-1)。

由于这个 f(0,l-1) 的 xor 和 f(0,r)=f(l,r) 的 xor(通过给定的等式),我们已经最大化了 f(0, l-1) 和 f(0,r),我们找到了子数组的最大异或(直到第 i 个元素)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-31
    • 1970-01-01
    • 2023-01-25
    • 2020-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多