【问题标题】:Counterexample for algorithim to find duplicates in an Array (python)在数组中查找重复项的算法的反例(python)
【发布时间】:2022-07-16 21:59:41
【问题描述】:

感谢您抽出宝贵时间回答一个非常简单的问题。我最近遇到了一个编码挑战,在优化之后,我做了一个算法,我确信它不起作用,但找不到破坏它的测试用例。比我更有经验的人可以给我一个不起作用的测试用例吗?你还能验证算法是 O(n) 时间和 O(1) 空间复杂度吗?这就是问题所在。

挑战:

编写一个从整数数组返回重复整数的算法。该数组的构造使得每个整数都大于 1(含)且小于数组的长度(不含)。

输入:

一个大小为 N 的整数数组,其中每个整数 x 都遵循规则 1

输出:

在输入中重复的整数。

示例:

输入:[1, 2, 3, 1]
输出:1

输入:[2, 3, 4, 2, 4]
输出:2 或 4

不应该工作的算法:

def find_duplicates(arr):
    curr_n = arr[0]
    while True:
        removed_n = arr[curr_n]
        if removed_n == curr_n:
            return curr_n
        arr[curr_n] = curr_n
        curr_n = removed_n

【问题讨论】:

  • 你确定有反例吗?我尝试随机生成一百万个测试输入,但我找不到任何没有给出正确答案的输入。
  • 具体是什么测试用例失败了呢?代码似乎可以工作,虽然有点混乱(为什么不使用 set?)
  • @NickODell 我实际上不确定。我们在面试过程中花了一两分钟试图提出一个反测试。我根本找不到,所以我认为我的逻辑可能存在一些缺陷,但似乎并非如此......
  • @EricJin 一开始我使用的是 dict,但面试官希望在保持 O(n) 时间复杂度的同时降低空间复杂度。所以我们结束了一起破解这段代码。

标签: python arrays algorithm


【解决方案1】:

你的算法是 O(n)。

每次迭代,它都会为某个索引 i 设置 arr[i] = i,或者如果 arr[i] == i 已经设置则停止。它只能修复 O(n) 个索引,因此需要 O(n) 时间。

你的算法也有效。其实挺好的。

如果我们在arr[i] == i 时认为一个数字“在正确的位置”,那么在循环的每次迭代开始时,我们就知道我们从一个错误中得到了curr_n地方。我们在第一次迭代时就知道这一点,因为数组中没有 0,所以arr[0] 总是在错误的位置。我们在后续迭代中知道这一点,因为我们使用if removed_n == curr_n 进行检查。

所以我们知道curr_n 来自错误的地方。如果我们在 right 位置也找到了相同的数字,那么它是重复的,我们将其返回。

如果你只是更改变量名,它的工作原理就会变得更加清晰:

def find_duplicate(arr):
    misplaced = arr[0]
    while True:
        replacing = arr[misplaced]
        if replacing == misplaced:
            return misplaced
        arr[misplaced] = misplaced
        misplaced = replacing

【讨论】:

  • 感谢您的澄清。这真的,真的,真的让我确信我的逻辑是正确的,并且我没有在逻辑上犯一些严重的错误。
【解决方案2】:

循环检测方法

def duplicate(arr):
    slow = arr[arr[0]]
    fast = arr[arr[arr[0]]]
    while slow != fast:
        slow = arr[slow]
        fast = arr[arr[fast]]
    fast = arr[0]
    while slow != fast:
        slow = arr[slow]
        fast = arr[fast]
    return slow

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-01
    • 1970-01-01
    • 2016-06-23
    • 1970-01-01
    • 2018-05-16
    相关资源
    最近更新 更多