【问题标题】:Algorithm to find a duplicate entry in constant space and O(n) time在恒定空间和 O(n) 时间中查找重复条目的算法
【发布时间】:2012-01-05 19:26:31
【问题描述】:

给定一个包含 N 个整数的数组,使得只有一个整数重复。在 O(n) 时间和常数空间中找到重复的整数。整数的值或N的值没有范围

例如,给定一个由 6 个整数组成的数组,即 23 45 67 87 23 47。答案是 23 (我希望这涵盖了模棱两可和模糊的部分)

我在网上搜索,但找不到任何整数范围不固定的问题。 here 也是一个例子,它回答了一个与我类似的问题,但在这里他创建了一个 C++ 中具有最高整数值的哈希表。但是 cpp 不允许这样创建一个具有 2^64 元素的数组(在 64-位计算机)。

很抱歉在数组不可变之前没有提到它

【问题讨论】:

  • 好问题。但是,您对答案的想法或尝试都不见了。
  • 找到了!我可以保留它吗?
  • @Constantinius:你是说这是一个简单的问题吗?我自己没有看到解决方案,我认为不存在。
  • "。但是 cpp 不允许这样创建具有 2^64 元素的数组(在 64 位计算机上)。" 你是什么意思?跨度>

标签: c++ algorithm


【解决方案1】:

Jun Tarui 有shown,任何使用 O(log n) 空间的重复查找器都需要至少 Ω(log n / log log n) 通过,这超过了线性时间。 IE。即使您允许对数空间,您的问题也可能无法解决。

Gopalan 和 Radhakrishnan 提出了一个有趣的 algorithm,它可以在输入和 O((log n)^3) 空间中一次性找到重复项,这听起来是您最好的先验选择。

Radix sort 的时间复杂度为 O(kn),其中 k > log_2 n 通常被视为一个常数,尽管它很大。显然,您无法在常量空间中实现基数排序,但您也许可以重用输入数据的空间。

如果您假设有关数字本身的特征,则存在数字技巧。如果几乎所有介于 1 和 n 之间的数字都存在,那么只需将它们相加并减去 n(n+1)/2。如果所有数字都是素数,则可以通过忽略除法的运行时间来作弊。

顺便说一句,比较排序有一个众所周知的 Ω(log_2(n!)) 下限,这表明 google 可能会帮助您找到简单问题(例如查找重复项)的下限。

【讨论】:

  • 比较排序的下限是 Ω(n log n)。请参阅Introduction to Algorithms 中的第 8 章以获得证明。
  • 是的,这是斯特林的近似值。
  • @JeffBurdges 数组是不可变的
  • @Jeff:是的,你是对的。我只是不习惯看到写成 Ω(log_2(n!))。太多火鸡,太晚了:-)
  • @Anubhav Agarwal 很好,无论如何在 O(kn) 中声明 k 常数是作弊,但 Tarui 证明不存在解决方案,所以唯一的问题是:如何作弊?面试官问这个问题时,他们说的可能是线性空间,除非你面试的是复杂性理论教授。
【解决方案2】:

如果数组没有排序,只能在O(nlogn)进行。

一些方法可以在here找到。

【讨论】:

  • 给出的链接并没有告诉你在恒定空间中进行操作。不能使用 2^64 数字的散列,因为 c++ 不允许这样的内存空间
  • @AnubhavAgarwal:C++ 肯定允许 2^64 个元素的哈希表;语言中没有什么可以禁止的。
  • @larsmans 谢谢你告诉我。但我仍然想要一个不使用这种方法的答案
  • @larsmans Exabyte DIMM 仍然相当昂贵。 ;) 见:superuser.com/q/168121/97386
【解决方案3】:

如果整数的范围是有界的,您可以在 O(n) 时间内执行counting sort 变体。空间复杂度为 O(k),其中 k 是整数 (*) 的上限,但这是一个常数,因此为 O(1)。

如果整数的范围是无限的,那么我认为没有办法做到这一点,但我不是复杂性难题的专家。

(*) 这是 O(k),因为每个整数的出现次数也有一个恒定的上限,即 2。

【讨论】:

  • 计数排序只是位向量的一般情况。
  • @HotLicks:是的,位向量是您实现此功能的方式。我懒得拼出算法。
【解决方案4】:
【解决方案5】:

在时间上最接近 O(N) 的方法可能是传统的哈希表,其中哈希条目只是用作键的数字。在首先检查它是否已经在表中之后,您将遍历列表,将每个条目插入哈希表中。

然而,并不是严格意义上的 O(N),因为散列搜索/插入会随着表的填满而变慢。而且在存储方面,大型列表的成本会很高——至少是数字数组大小的 3 倍,可能是 10-20 倍。

【讨论】:

  • 你的答案没有固定空间
  • 是的。没有绝对符合规范的实用算法。
【解决方案6】:

正如其他人已经提到的那样,我看不出有任何方法可以在 O(n) 中做到这一点。

但是,您可以使用Bloom Filter 尝试概率方法。如果幸运的话,它会给你 O(n)。

【讨论】:

  • 非常有趣的数据结构。
【解决方案7】:

由于不允许额外的空间,所以没有比较就不能做到。这里可以应用comparison sort的时间复杂度下限的概念来证明原始形式的问题无法解决O(n) 在最坏的情况下。

【讨论】:

    【解决方案8】:

    这里我们也可以在线性时间 o(n) 内完成

    public class DuplicateInOnePass {
    
        public static  void duplicate()
    
       {
            int [] ar={6,7,8,8,7,9,9,10};
            Arrays.sort(ar);
            for (int i =0 ; i <ar.length-1; i++)
            {
    
    
                if (ar[i]==ar[i+1])
                    System.out.println("Uniqie Elements are" +ar[i]);
    
            }  
    
        }
    
        public static void main(String[] args) {
            duplicate();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-02-22
      • 2011-08-09
      • 2015-05-25
      • 2017-04-06
      • 2012-08-06
      • 1970-01-01
      • 1970-01-01
      • 2011-05-13
      • 2012-01-02
      相关资源
      最近更新 更多