在数组中查找重复元素?

Posted

技术标签:

【中文标题】在数组中查找重复元素?【英文标题】:Finding duplicate element in an array? 【发布时间】:2011-02-04 06:09:09 【问题描述】:

看到一个面试题如下:

数组中有一个数重复。找到它

简单的解决方法如下:

for(int i=0;i<n;i++)
  
    dup = false;
    for(j=0;j<n;j++)
        if(i!=j && a[i]= a[j])
            dup = true;
        

       if(dup == true)
          return a[i]
     

但我想在 O(n log(n)) 和 O(n) 时间内实现它。我该怎么做?

【问题讨论】:

您是用 C++ 还是 Java 编程?如果您的问题与语言无关,请删除特定于语言的标签。 【参考方案1】:

对数组进行排序(可以在第一个 O (n Log n) 中完成,然后只需对相邻元素进行比较。或者只需将数组放入哈希表中,如果找到第一个键就停止已有条目。

【讨论】:

【参考方案2】:

我正在回答“在数组中查找重复元素?”

从 0 到

for (int i=0; i<n-1; i++) 

    for (j=i+1; j<n; j++)
    
         if (a[i] == a[j])
         
            return i;
         
    

return -1; 

反复设置 dup=false 是无稽之谈。要么 dup 仍然是假的,要么是真的,然后你留下了'return'的代码。

【讨论】:

【参考方案3】:

用实际代码(Java)编写前面的答案:

O(n log n) 时间:

    Arrays.sort(arr);
    for (int i = 1; i < arr.length; i++)
        if (arr[i] == arr[i - 1])
            return arr[i];
    throw new Exception(); // error: no duplicate

O(n) 时间:

    Set<Integer> set = new HashSet<Integer>();
    for (int i = 0; i < arr.length; i++) 
        if (set.contains(arr[i]))
            return arr[i];
        set.add(arr[i]);
    
    throw new Exception(); // error: no duplicate

【讨论】:

如果存在冲突,基于哈希表的数据结构可能具有 O(n^2) 的最坏情况复杂度。由于红黑树是自平衡树,因此基于树的数据结构的最坏情况复杂度为 O(nlogn)。 制作Set&lt;Integer&gt; set = new HashSet&lt;&gt;(arr.length);(如果接近开始的重复概率很低 - 如果它很高,你最好使用Set的树实现)。使用 foreach 循环。只需添加元素并返回 if !Set.add(arr[i]).【参考方案4】:

Reference java.util.TreeSet 是底层实现的红黑树,O(n*log(n))

【讨论】:

【参考方案5】:

推荐使用hash-map(假设没有冲突)来解决它。

 private boolean hasDuplicate(int[] arr) 
        Map<Integer, Boolean> map = new HashMap();
        // find the duplicate element from an array using map
        for (int i = 0; i < arr.length; i++) 
            if(map.containsKey(arr[i])) 
                return true;
             else 
                map.put(arr[i], true);
            
        
        return false;
    

时间复杂度:O(n)

空间复杂度:O(n)

另一种方法是排序和比较,但排序会增加额外开销

【讨论】:

【参考方案6】:

通过使用集合,我们可以使用下面的代码 sn-p -

Set<String> set = new HashSet<String>();
    for (String arrayElement : arr) 
        if (!set.add(arrayElement)) 
            System.out.println("Duplicate Element is : " + arrayElement);
        
    

【讨论】:

【参考方案7】:

如下找到 O(n) 复杂度解决方案 -

int ar[]=0,1,2,3,0,2,3,1,0,2;
    Set  <Integer>mySet=new HashSet<>();
    for(int n:ar)
        if(!mySet.add(n))
            System.out.println(" "+n);
        
    

还有另一个空间复杂度较小的过程 O(N) 并且可能 O(n Log n) --

    public void duplicateElementSolution(int ar[])
     Arrays.sort(ar);

    for(int i=0;i<(ar.length-1);i++)
        if(ar[i]==ar[i+1])
            System.out.println(" "+ar[i]);
        
    
  

【讨论】:

【参考方案8】:

(当前形式的问题有点令人困惑 - 我的答案是假设问题是关于在数组中找到两个数字,总和为给定值)

由于给定的数组是未排序的,我假设我们不允许对数组进行排序(即不能更改数组的给定顺序)。

恕我直言,最简单的解决方案是遍历每个数字 x 并检查 I-x 是否出现在数组中的任何位置。这基本上就是您的 O(n^2) 解决方案正在做的事情。

通过使用某种快速集合数据结构使搜索更快,可以将其降低到 O(n) 或 O(nlogn)。基本上,当我们遍历数组时,我们会查询I-x 是否出现在集合中。

代码(在 Python 中):

l=[1,2,3,4,5,6,7,8,9]
seen=set()

I=11
for item in l:
        if I-item in seen:
                print "(%d,%d)"%(item,I-item)
        seen.add(item)

解决方案的复杂性取决于您使用的set 数据结构的插入/查找复杂性。基于哈希表的实现具有 O(1) 复杂度,因此它为您提供 O(n) 算法,而基于树的 set 导致 O(nlogn) 算法。

编辑:

与 Python 的 set 等效的数据结构在 C++ 中是 stl::set,在 Java 中是 TreeSet/HashSetI-x in seen 行将在 Java 中转换为 seen.contains(I-x),在 C++ 中转换为 seen.find(I-x)==seen.end()

【讨论】:

不是很懂,对python也不是很熟悉。U只是在set中添加item,这个codeE中如果sum = i怎么查? @mindtree:正如我在代码前面的解释中所说,如果 a+b=X 我们有 b=X-a。所以我们只检查 X-a 是否在之前遇到的数字集合中(使用表达式I=item in seen)。 该问题已被编辑,远离此假设,因此删除此答案可能会更好。

以上是关于在数组中查找重复元素?的主要内容,如果未能解决你的问题,请参考以下文章

在对象数组中查找所有匹配的元素[重复]

在 O(1) 空间中的数组中查找重复元素(数字不在任何范围内)

编写在数字数组中查找元素索引的函数[重复]

在线性时间和恒定空间中查找数组中缺失和重复的元素

在两个数组中为javascript查找缺少的元素[重复]

查找字符串中存在哪个数组元素[重复]