我们有两个未排序的数组,每个数组的长度为n。这些数组包含0-n 100 范围内的随机整数。如何找出这两个数组在O(n)/线性时间内是否有任何共同元素?不允许排序。
答案 0 :(得分:11)
Hashtable会救你。真的,它就像算法的瑞士刀 只需将第一个数组中的所有值放入其中,然后检查第二个数组中是否存在任何值。
答案 1 :(得分:6)
您尚未定义计算模型。假设你只能在O(1)时间内读取O(1)位(其他任何东西都是一个相当奇特的计算模型),那么就没有算法可以解决O(n)最坏情况时间复杂度的问题。
证明草图: 输入中的每个数字取O(log(n ^ 100))= O(100 log n)= O(log n)位。因此整个输入为O(n log n)位,在O(n)时间内无法读取。因此,任何O(n)算法都不能读取整个输入,因此如果这些位重要则不作出反应。
答案 2 :(得分:2)
回答尼尔: 由于您在开始时就知道您的N(两个大小为N的数组),您可以创建一个数组大小为2 * N * some_ratio的哈希(例如:some_ratio = 1.5)。使用此大小,几乎所有简单的哈希函数都将为您提供良好的实体传播。
您还可以实现find_or_insert以搜索现有或在同一操作中插入新的,这将减少散列函数和比较调用。 (c ++ stl find_or_insert不够好,因为它没有告诉你该项目之前是否存在)。
答案 3 :(得分:2)
线性测试
使用Mathematica哈希函数和任意长度的整数。
测试直到 n = 2 ^ 20 ,生成随机数,直到(2 ^ 20)^ 100 =(约10 ^ 602)
以防万一...程序是:
k = {};
For[t = 1, t < 21, t++,
i = 2^t;
Clear[a, b];
Table[a[RandomInteger[i^100]] = 1, {i}];
b = Table[RandomInteger[i^100], {i}];
Contains = False;
AppendTo[k,
{i, First@Timing@For[j = 2, j <= i, j++,
Contains = Contains || (NumericQ[a[b[[j]]]]);
]}]];
ListLinePlot[k, PlotRange -> All, AxesLabel -> {"n", "Time(secs)"}]
答案 4 :(得分:1)
如果存储不重要,则抓取哈希表以支持长度为n的数组。当您在第一个数组中遇到该数字时,标记为true。在传递第二个数组时,如果你发现它们中的任何一个是真的,那么你就得到了答案。为O(n)。
Define largeArray(n)
// First pass
for(element i in firstArray)
largeArray[i] = true;
// Second pass
Define hasFound = false;
for(element i in secondArray)
if(largeArray[i] == true)
hasFound = true;
break;
答案 5 :(得分:1)
将第一个数组的元素放在哈希表中,并检查是否存在扫描第二个数组。这为您提供了O(N)平均值的解决方案。
如果你想要一个真正的O(N)最坏情况解决方案,那么使用0-n ^ 100范围内的线性数组而不是使用哈希表。请注意,每个条目只需要使用一个位。
答案 6 :(得分:0)
你试过counting sort吗?它易于实现,使用O(n)空间并且还具有\ theta(n)时间复杂度。
答案 7 :(得分:0)
基于发布到日期的想法。我们可以将一个数组整数元素存储到哈希映射中。 RAM中可以存储不同整数的最大数量。哈希映射只有唯一的整数值。重复项被忽略。
以下是Perl语言的实现。
#!/usr/bin/perl
use strict;
use warnings;
sub find_common_elements{ # function that prints common elements in two unsorted array
my (@arr1,@array2)=@_; # array elements assumed to be filled and passed as function arguments
my $hash; # hash map to store value of one array
# runtime to prepare hash map is O(n).
foreach my $ele ($arr1){
$hash->{$ele}=true; # true here element exists key is integer number and value is true, duplicate elements will be overwritten
# size of array will fit in memory as duplicate integers are ignored ( mx size will be 2 ^( 32) -1 or 2^(64) -1 based on operating system) which can be stored in RAM.
}
# O(n ) to traverse second array and finding common elements in two array
foreach my $ele2($arr2){
# search in hash map is O(1), if all integers of array are same then hash map will have only one entry and still search tim is O(1)
if( defined $hash->{$ele}){
print "\n $ele is common in both array \n";
}
}
}
我希望它有所帮助。