在O(N)时间内查找数组中的重复项
Find Duplicates in an array in O(N) time
是否有一种方法可以在O(N)时间内找到N个元素数组中的所有重复元素?
的例子:
输入:11, 29, 81, 14, 43, 43, 81, 29
输出:29, 81, 43
对输入进行排序并进行线性扫描以检测重复项,破坏了顺序并给出输出:29,43,81。
根据给定数组对另一个索引数组{0,1,...N-1}
按键排序得到{1,4,2}
,然后对结果索引集排序得到{1,2,4}
,将得到{29,81,43}
,但这需要O(N logN)
时间。
是否存在O(N)算法来解决这个问题?
注:我忘了补充:我不想用哈希表。我正在寻找一个非哈希解决方案。
我认为一个好的解决方案(体面的内存使用,可以用来立即确定条目是否已经被看到,从而保持顺序,并具有线性复杂性)是一个trie。
如果您将元素插入到树中,就好像它们是每个节点中每个数字(从MSD开始)的字符串一样,您可以以0 (m N)的复杂度完成此操作,其中m是以10为基数的数字的平均长度。
你只需要循环遍历所有条目并将它们插入到树中。每当一个元素已经存在时,就跳过它,继续下一个元素。这里的重复项(不像我之前对基数排序的回答)将立即找到,而不是在最后一次迭代中找到。
我不确定您是否会从这里使用后缀树中受益,因为输入到树中的字符的"基数"只有10(与ANSI字符串的基数128相比),但这是可能的。
如果你的输入都是小整数,你可以使用计数排序,它在O(n)时间内运行,需要O(m)空间,其中m是可能输入范围的大小。
作为空间优化,使用位数组并使用单个位(而不是计数)来存储您之前是否见过该项就足够了。
听起来您反对分配任何额外的空间。尽管如此,哈希表仍然是提高速度的正确解决方案。老实说,大多数用于简单数据(如整数)的哈希表实现都过于单一解决方案,以至于我只能根据自己的需要自行制定。当你需要它做一些相对较少的工作时,它可以把慢代码变成快代码。
同样,如果你反对哈希表是因为它们破坏了顺序,那么你可能想要稍微不同地使用它们来获得期望的O(n),同时保持顺序:
创建一个哈希表,将数组元素映射为2位,作为从0到3的计数字段,并将30位作为元素数组的索引。除非你的数组中有超过10亿个值,否则30位就足够了。这样你的哈希值就是一个32位的单词。
遍历数组中的元素。如果某个元素不在表中,则将该值插入哈希表并将count字段设置为零。当你存储它的时候,索引部分是什么并不重要。如果元素在表中,并且count字段为零,则将其提高到1,并使用新的count字段值存储元素索引。如果count字段已经是1或更大,则将其设置为2,并且不要触及存储的索引—保持它不变。
再次遍历数组中的元素。查找每个元素,如果它的索引是存储的,并且相关的count字段大于零,则将其打印出来。
这将在O(n)时间内以适当的顺序产生您想要的结果。但是,由于未知的原因,它使用了不需要的哈希表。我强烈建议您要么接受这样的解决方案,要么解释其局限性,以便获得更准确的目标解决方案。
如果你知道最大值,你可以这样做
有一个单独的数组,其长度为最大值
int[max] secondarray;
for(int i=o;i<arrayFirst.length;i++){
if(secondarray[arrayFirst[i]]==0){
secondarray[arrayFirst[i]]==arrayFirst[i];
}else{
result.add(arrayFirst[i]);
}
}
您可以在0 (n)内完成此操作,但是这将要求数组为整数。所需的空间大小可以为-2^32到2^32。你需要做的是找到原始数组的最大值和最小值。然后生成两个数组(arraynew+)和(arraynew-)
(arraynew+)的大小为max(arraorig)-min(arrayorig)如果arrayorig中的所有值都是+,则(arraynew+)的大小为max(arrayorig)。
如果所有值都为正,则size (arraynew-)将为零,否则它们将等于min(arrayorig)的绝对值。
然后你可以遍历数组,并在数组值对应的索引处增加1 (arraynew-)或(arraynew+)的值,如果值是正的,应该增加(arraynew+),否则如果它的负增量应该在(arraynew-)的索引处做(arraynew-),这等于数组的绝对值。那么所有值>1的(arraynew+)和((arraynew-)的索引都是arrayorig的不同值。
void printRepeating(int arr[], int size)
{
int i;
printf("The repeating elements are: n");
for (i = 0; i < size; i++)
{
if (arr[abs(arr[i])] >= 0)
arr[abs(arr[i])] = -arr[abs(arr[i])];
else
printf(" %d ", abs(arr[i]));
}
}
查找重复项就像排序一样困难。最好的办法是利用输入的某些属性来获得O(N)排序。
- 在数组中查找总计
- 在二维数组中查找最小值和最大值?
- 如何查找哪个类对象位于数组的特定索引上(多态性)
- 查找自动生成键并具有线性内存消耗的小型关联数组
- C++ 使用存储在动态数组中的文本文件中的数据查找模式
- 查找数组中第一个最小值和最后一个最大值元素之间的算术平均值
- 如何使用数组查找标准偏差
- 从列表到数组C 查找模式或最常见的数字
- 12个元素的数组 - 查找计数实践
- 使用数组查找HCF,获取未知输出(C )
- C++constexpr数组查找:内存开销?其他问题
- C++字符数组查找/替换字符
- 动态数组查找能力
- 用.用数组查找.C++
- 使用数组查找最大值
- 字典查找与数组查找;数组分配与字典分配
- 使用数组查找最接近的数字C++,浮点
- 定义一个非常大的数组(查找表)的最佳方式是什么
- Std::数组查找最大值函数
- Python在简单数组查找上的小循环的性能问题