【问题标题】:Find duplicate in an array without changing inputs?在不更改输入的情况下在数组中查找重复项?
【发布时间】:2020-03-30 17:35:48
【问题描述】:

给定一个常量数组,其整数范围为 [1...N],数组长度为 N+1。 该数组包含至少一个副本,我们需要在恒定空间和线性时间中找到该副本,而不会破坏输入。 我被卡住了,然后我终于看到了使用弗洛伊德循环查找算法的解决方案,如何证明它有效?

【问题讨论】:

  • 您能否具体说明您的解决方案是如何工作的?不同情况下的证明可能不同
  • 顺便说一句,您可以计算从 1 到 N 的数字的 XOR,我们称之为 XOR1,然后 XOR2 将是您数组中数字的 XOR。那么你的副本等于 XOR1 XOR XOR2。
  • 实际上我还没有解决它我已经看到他们使用弗洛伊德算法来检测循环并找到循环的入口点的解决方案,根据解决方案将始终是重复元素.
  • @Maras 但数组可以包含多个重复项,我认为 XOR 解决方案在这种情况下不起作用。
  • 没关系,你是对的 ;)

标签: arrays algorithm optimization


【解决方案1】:

如果我们将“不改变输入”解释为数组必须保持与开始时相同的状态,那么我们可以作弊:数字在 1..N 范围内,所以我们可以存储使用超出此范围的数字的额外信息,只要我们之后将原始数字放回即可。一个简单的方案是将x 翻转为-x 以存储额外的 N+1 位信息,而无需分配 O(N) 额外的内存。找到答案后,通过将所有负值翻转回来,可以在线性时间内恢复原始状态。

当值i 在数组中时,该解决方案通过翻转索引i 处的值来工作。如果它已经翻转,则 i 是重复的。下面是一个 Python 示例:

def find_duplicate(arr):
    result = -1
    for i in arr:
        if arr[i] < 0:
            result = i
            break
        arr[i] *= -1

    # restore original state
    for i in range(len(arr)):
        if arr[i] < 0:
            arr[i] *= -1

    return result

【讨论】:

  • 给定的数组是不可变的,你不能在任何时候改变它的状态。
  • @George you can't change its state at any point of time - 您的问题描述中未指定。此解决方案完全符合您当前的描述。
  • @Anatolii 我在问题中明确指出不能销毁输入。
  • 此解决方案不会破坏输入;它让他们保持原样。
【解决方案2】:

考虑数组槽,编号为 1 到 N+1。

每个插槽中都有一个数字,我们可以将其视为其“后继”插槽的指针。

从插槽 N+1 开始并跟随指针。每个槽都有一个指针,所以我们可以永远跟随它们,但是只有 N 个槽,所以在某些时候我们会看到一个我们以前见过的指针,这让我们进入了一个循环。

我们看到两次的 first 指针是一个重复的数字。证明如下:

给定任何槽 x,如果 x 仅被访问一次,我们可以说 x 是“循环外”,并且“在循环内”循环”,如果我们多次访问它。

如果一个槽x在循环之外,那么:

  • 如果槽 x 中的指针再也见不到,那么槽 x 的后继者也在循环之外;
  • 如果再次看到槽 x 中的指针,则将再次访问 x 的后继对象,并且它在循环内。

显然,slot N+1 在循环之外,因为指针的范围仅从 1 到 N。

由于我们从循环外的槽开始,并且我们最终必须访问循环内的槽,因此循环内的槽在循环外有一个前驱。然而,由于它将再次被访问,并且循环外的节点只能看到一次,因此它还必须有一个位于循环内的前驱,因为这是我们可以返回到它的唯一方法。

因此,该槽的编号至少出现在其他两个槽中——它的前辈——并且是数组中的重复元素。

【讨论】:

    猜你喜欢
    • 2015-05-18
    • 1970-01-01
    • 2022-11-21
    • 2013-10-02
    • 2015-10-07
    • 2021-12-02
    • 2014-01-10
    • 2021-06-09
    • 2015-03-28
    相关资源
    最近更新 更多