【问题标题】: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 编程?如果您的问题与语言无关,请删除特定于语言的标签。

标签: java c++ algorithm


【解决方案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)。
              • 该问题已被编辑,远离此假设,因此删除此答案可能会更好。
              猜你喜欢
              • 1970-01-01
              • 2020-08-21
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-06-06
              • 2017-08-18
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多