在数组中查找重复元素?
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<Integer> set = new HashSet<>(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
/HashSet
。 I-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
)。
该问题已被编辑,远离此假设,因此删除此答案可能会更好。以上是关于在数组中查找重复元素?的主要内容,如果未能解决你的问题,请参考以下文章