在数组中查找重复元素?

时间:2011-02-04 06:09:10

标签: java c++ algorithm

我看到一个面试问题如下:

数组中的一个数字是重复的。找到它

简单的解决方案如下:

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)时间内实现它。我该怎么办?

8 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:3)

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

搜索i和j从0到&lt; n,然后你检查j!= i。相反,你可以像这样形成你的循环:

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'。

答案 2 :(得分:2)

在实际代码(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

答案 3 :(得分:0)

参考java.util.TreeSet实施红黑树底层,它是 O(n * log(n))

答案 4 :(得分:0)

建议使用 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)

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

答案 5 :(得分:0)

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

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

答案 6 :(得分:0)

如下所示找到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]);
        }
    }
  }

答案 7 :(得分:-1)

(当前形式的问题有点令人困惑 - 我的答案是假设问题是在数组中找到两个数字并求一个给定值)

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

最简单的解决方案IMHO将迭代每个数字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 / HashSet。行I-x in seen将在Java中转换为seen.contains(I-x),在C ++中转换为seen.find(I-x)==seen.end()