【问题标题】:Find the two numbers that appear only once - divide and conquer找出只出现一次的两个数字——分而治之
【发布时间】:2020-09-17 07:04:09
【问题描述】:

给定一个数组,其中每个元素出现两次,我必须找出数组的哪两个数字只出现一次。最大额外内存为 O(1)。

我找到了这个惊人的解决方案:https://medium.com/@gurupad93/two-numbers-that-appear-once-b89e92a9334b

问题是我的解决方案应该是分而治之,而我的理解是我找到的解决方案不是。

当出现一次的元素只有一个时,我知道如何用分而治之解决这个问题。在这里,老实说,我不知道如何递归地划分数组。

有什么建议吗?

非常感谢!

【问题讨论】:

  • 对我来说听起来像是家庭作业。所以也许关于要执行的任务的问题应该直接交给家庭作业指导员。

标签: algorithm time-complexity bit-manipulation divide-and-conquer


【解决方案1】:

选择第一位。

设置此位的数字与此位为零的数字分开。

您可以在快速排序中使用分区之类的例程 - 用一位找到最左边的数字,用零位找到最右边的数字,交换它们,继续直到左右索引相遇。

处理左侧和右侧部分,考虑下一位。

使用下一位递归执行此操作,直到部分大小变为 1 或 2。

在第一种情况下,您找到了一个需要的数字。

在第二种情况下,检查数字是否不同。


我希望这些线索可能有助于实现可能的分而治之的方法。

【讨论】:

  • 分而治之似乎是合理的。我想知道,当您认为这个问题不值得投票时,为什么还要费心回答?
【解决方案2】:

我假设这些数字是正整数。该列表具有偶数个元素。您计算平均值并将列表分为两个子列表,低于和高于平均值。然后要么都有奇数个元素,要么都是偶数。在奇怪的情况下,您知道每个子列表都包含一个单例,并且您解决了每个子列表的单例问题。在偶数情况下,您知道其中一个子列表没有单例,即配对,而另一个有两个。您决定将哪一个配对并继续处理另一个,递归地解决两个单例问题。

如果整数以标准二进制表示,您可以对所有整数进行异或以确定它们是否成对。否则,如果它们以 BCD、浮点或代表不唯一的任何形式表示,则可以使用以下测试: 当且仅当所有元素的乘积是平方时,整数列表才成对。计算 exp( 1/2 sum( log xi ) ),如果它是整数,则列表成对,否则不成对。

但链接中的解决方案无疑比这要好得多。

【讨论】:

  • 我不明白你的第二段,但第一段中的算法似乎是正确的——只要你在编码时非常小心边界条件。边界条件对于类似快速排序的算法来说是出了名的棘手,并且由于选择分区值的方式(包括舍入),这里可能会更糟。我想知道,当您认为这个问题不值得投票时,为什么还要费心回答?
  • @davidbak 我现在已经投票了。好问题。并且链接的解决方案更好。
  • 我终于自己解决了,这是我的解决方案,如果有任何反馈,我将不胜感激:我将数组分成比中位数更小和更大的两个元素。我检查了在两者中创建一个元素的算法。两个选项,如果两个结果都在同一个子数组上(都在左边或都在右边),两个子数组的结果之一将为 0,所以我丢弃它并递归地继续。其他选项,它们是分开的,在这种情况下,两个结果都不会是 0,并且一次性算法的两个结果将恰好是两个数字。我添加了一个答案以更好地解释。
【解决方案3】:

我能够找到我的问题的算法:

我找到数组的中位数并使用分区将所有较小的元素放在中位数的左侧,将所有较大的元素放在右侧。

我有一个算法能够在出现一次的元素只有一个时返回(对所有元素使用 XOR)。如果没有元素只出现一次,则异或结果为 0。

我在两个子数组上都运行这个算法,两个选项:

  • 如果算法在一个数组上输出0,那么肯定该元素不在这个子数组中,我们在另一半递归调用函数。

  • 如果(且仅当)算法输出两个不同于 0 的数字,这意味着结果在数组中被分开。在这种情况下,这两个数字也将是问题的结果。

请注意,除了这两个之外没有其他选项。

空间复杂度为 O(1)

时间复杂度:我们有一些成本为 O(n) 的操作,我们在每次迭代时除以数组的一半,我们得到:

T(n) = T(n/2) + O(n) -> (主定理) -> O(n)

【讨论】:

  • 这不是@Henrik4 的回答吗?
  • 跟我的很像。如果你是独立完成的,那就太好了。
  • 是的,非常相似!我的解决方案要注意一点,如果结果为 0,我还必须检查元素的数量是否为偶数,这是因为数字 0 本身也可以是结果值。成本为 O(n) 表示整个实现的成本,我进行了编辑以使其更清晰
  • @saraspagno 你的意思是 0 可以是单例?在你走之前将所有数字加 1 来排除它。
【解决方案4】:

问题可以划分为树形结构(类似于归并排序的树形结构),每个分区将其元素的异或值返回给父级。这样我们就得到了数组中只出现一次的两个数的异或值。

从问题中可以看出,异或值至少有一个非零位。

让我们假设 xor 值为 X 并且其第 i 位非零。

现在我们再次将问题划分为树结构,并考虑设置了第 i 位的元素进行异或计算。该值返回给父级。根节点将获取设置了第 i 位的元素的异或值。让我们将此值称为 Y。

因此,这两个数字是 YX xor Y

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-26
    • 2021-12-06
    • 2018-04-03
    • 1970-01-01
    • 2018-09-25
    • 2014-08-15
    • 2016-01-20
    • 2013-01-12
    相关资源
    最近更新 更多