【问题标题】:Find duplicates in a array/list of integers在整数数组/列表中查找重复项
【发布时间】:2016-11-18 02:09:42
【问题描述】:

给定array/listintegers,输出重复项。

另外,我真正在寻找什么:哪些解决方案具有最佳的时间性能?最佳空间表现?是否有可能同时拥有最佳时间和最佳空间性能?只是好奇。谢谢!

例如:给定列表[4,1,7,9,4,5,2,7,6,5,3,6,7],答案将是[4,7,6,5](输出顺序无关紧要)。

我在python 中写下了我的解决方案。

这是我使用哈希和二进制搜索编写的一个解决方案。

def binarySearch(array, number):
    start = 0
    end = len(array)
    mid = (end + start) // 2
    while (end > start):
        mid = start + (end - start) // 2
        if array[mid] == number:
            return (mid, True)
        elif number > array[mid]:
            if start == mid:
                return (mid + 1, False)
                start = mid
            else:
                end = mid

    return (mid, False)

def findDuplicatesWithHash(array):
    duplicatesHash = {}
    duplicates = []
    for number in array:
        try:
            index,found = binarySearch(duplicates, number)
            if duplicatesHash[number] == 0 and not found: 
                duplicates.insert(index, number)
        except KeyError as error:
            duplicatesHash[number] = 0

    duplicatesSorted = sorted(duplicates, key=lambda tup: tup)
    return duplicatesSorted

【问题讨论】:

  • [1,1,2,3,4,4,5,5,5,6] - 这个输入数组的期望输出是什么?
  • "是否可以同时拥有最佳时间和最佳空间性能?"好问题!可能没有;)
  • @wookie919: [1,4,5]

标签: python arrays algorithm list sorting


【解决方案1】:

查找重复项有多种解决方案。鉴于这个问题是完全通用的,可以假设给定一个n 值列表,重复的数量位于[0, n/2] 范围内。

你能想到哪些可能的方法?

  1. 哈希表方法:

    如果哈希表中不存在值,则在遍历列表时存储值。如果该值存在,则您有一个重复项。

    Algorithm FindDuplicates(list)
    hash_table <- HashTable()
    duplicates <- List()
    for value in list:
        if value in hash_table:
            duplicates.add(value)
        else:
            hash_table.add(value, true)
    
    • 时间:O(n) 遍历所有值
    • 空格:O(n) 将所有可能的值保存在哈希表中。
  2. 排序数组

    对数组排序并遍历邻居值。

    Algorithm FindDuplicates(list)
    list.sort()
    duplicates <- Set()
    for i <- [1, len(list)-1]:
        if list[i] = list[i-1]:
            duplicates.add(list[i])
    
    • 时间:O(n.logn) + O(n) = O(n.logn)对所有值进行排序和遍历
    • 空格:O(1) 因为没有创建额外的空间来产生重复项
  3. 检查每个值

    为每个值检查该值是否存在于数组中。

    Algorithm Search(i, list):
        for j <- [0, len(list)-1] - [i]:
            if list[j] = list[i]:
                return true
        return false
    
    Algorithm FindDuplicates(list)
    duplicates <- Set()
    for i <- [1, len(list)-1]:
        if Search(i, list):
            duplicates.add(list[i])
    

    时间:O(n^2)比较次数为n*n(-1) 空格:O(1) 因为没有创建额外的空间来产生重复

注意:重复数组的空间不能包含在空间复杂度方程中,因为这是我们想要的结果。

你还能想出更多吗?

【讨论】:

  • 我想出的两个解决方案是你提到的前两种方法。不幸的是,我的哈希算法一定做错了,因为与排序数组方法相比,它的执行非常糟糕。
  • 对于非常小的数据集,您可能收到的结果可能并不能很好地表明您的算法的时间复杂度。尽管可以假设分配哈希表不需要时间,但在某些环境中创建哈希表和存储元素可能比就地排序数组要慢。尝试使用更大的数据集,例如 10K 值或 100 万个值,看看您的算法如何执行。
  • 我尝试了从 100 个元素到 100 万个元素之间的元素大小。当我使用大小为 10k、100k 和 100 万个元素的列表时,我注意到与排序数组方法相比,性能明显降低。
  • 您可以将代码添加为对原始帖子的编辑。我会调查一下。
  • @OhaiMac 我不确定代码是否应该工作。首先,二分查找应该在一个有序数组上。 AFAIU,duplicates 不是排序列表。此外,这个想法在这里似乎不正确。您不需要搜索重复数组。将此解决方案与我上面提到的哈希表方法(非常标准)进行比较,如果哈希表不存在,只需向哈希表添加一个数字。在哈希表中查找数字是 O(1)O(logn) 相比,在排序数组上进行二进制搜索。
【解决方案2】:

获取副本的一种方法:

l = [4,1,7,9,4,5,2,7,6,5,3,6]
import collections

print([item for item, count in collections.Counter(l).items() if count > 1])

【讨论】:

  • 很好的解决方案!真的很短很简洁。这比我使用排序提出的解决方案要快一些。但是,这个空间复杂度是多少?
【解决方案3】:

查找重复项与排序非常相似。也就是说,每个元素都需要直接或间接地与所有其他元素进行比较,以查找是否存在重复项。可以修改快速排序以输出具有 O(n) 空间复杂度和 O(n*log(n)) 平均时间复杂度的相邻匹配元素的元素。

【讨论】:

  • 好点!我想出的一个解决方案是使用字典和二进制搜索。不幸的是,这种方法不如我想出的其他方法好,基本上就是你上面提到的。
猜你喜欢
  • 2017-05-17
  • 2018-07-28
  • 2015-08-31
  • 2018-05-03
  • 2018-05-16
相关资源
最近更新 更多