Algorithm 查找与输入数组具有最大交集的数组的有效方法
假设我有一大组数组(大小可达数百万),我想确定(最好是精确的,尽管近似值很好)这个集合中与输入的交集最大的数组,什么是最有效的方法?我将在底部列出一些我脑海中闪过的解决方案,将其简化为另一个问题,但我不确定它们是否一定是最好的 这组数组可以存储在任何数据结构中,并且可以以任何方式对数组进行排序和存储。这里的想法是优化查询时间 示例:假设我的数组集是(为了方便起见,以类似基数的方式排序,可以选择任何方式排序): 我的输入数组是:Algorithm 查找与输入数组具有最大交集的数组的有效方法,algorithm,sorting,optimization,similarity,nearest-neighbor,Algorithm,Sorting,Optimization,Similarity,Nearest Neighbor,假设我有一大组数组(大小可达数百万),我想确定(最好是精确的,尽管近似值很好)这个集合中与输入的交集最大的数组,什么是最有效的方法?我将在底部列出一些我脑海中闪过的解决方案,将其简化为另一个问题,但我不确定它们是否一定是最好的 这组数组可以存储在任何数据结构中,并且可以以任何方式对数组进行排序和存储。这里的想法是优化查询时间 示例:假设我的数组集是(为了方便起见,以类似基数的方式排序,可以选择任何方式排序): 我的输入数组是: ('a', 'f') 那么相应的交叉点是: [('a'), ('a
('a', 'f')
那么相应的交叉点是:
[('a'), ('a', 'f'), ('f'), (), ('f'), ()]
因此,输出将是('a','f')
,具有大小为2的最大交点。作为奖励,最好有最大的K
,因此这里,如果K=3,输出将是(以任何顺序):
我想到了一些可能的解决方案:
- 我的域的大小受到限制(例如,它可以是a-z或
数字1-70等),所以我可以将它们表示为二进制
字符串,现在的挑战是找到最小哈明顿值
距离,我现在可以用类似于局部散列的方法来实现?例如,
可以表示为('a','f')
10000100000000000000000
- 另外,利用域受到限制的事实,我可以创建一些 反向索引,域中的项指向不同的 数组,然后为输入数组中的每个项相交(至少部分相交)这些结果-尽管我感觉像这样 效率极低(尤其是在十字路口转弯时 类似于谷歌搜索的工作原理,尽管我不知道他们算法的全部细节
感谢您对正确方向的任何回应或指点 我建议使用哈希集的直接方法。
如果哈希集得到了很好的实现,用一个好的哈希函数,那么我们可以考虑检查元素是否是这个集合的一部分,可以在<代码> O(1)< /C>中完成。 然后,我们可以执行以下操作:
function find_closest_arrays(A, B_1, ..., B_n) {
result = [0, ..., 0] // array of size n
for elem in A {
for i in 1 ... n {
if elem is in B_i {
result[i] ++
}
}
}
return result
}
此函数返回一个数组结果
result[i]
包含输入数组A
和B_i
之间共有的元素数从这里开始,获得
k
最佳值是非常直接的,您所要做的就是获得k
结果中最大数字的索引
该算法的时间复杂度为O(n*m)
,其中m
为输入数组的大小,而n
为数组集的大小。由于缺乏声誉,我事先无法通过评论提出一些问题:
所有数组都是唯一的,但每个数组本身就是一个集合吗
如果多个阵列共享最大的交叉点大小,是否需要列出所有阵列
您的输入可能比给定的最长数组长
迭代
如果没有hashset,我将按长度对数组进行排序,并从最长的数组开始,最后通过查找大于或等于较短数组大小的交集大小来跳过较短的数组
如果你也对数组本身进行排序,你可以利用哈明顿距离,但你不必同时对所有数组进行排序和转换,只需要从它们的一部分开始。如果不使用Hammington,请记住,如果将输入与大小为+1的数组进行比较,则只需进行比较,直到第一次比较时,输入的最后一个元素小于当前数组元素
f
因为k>f,我们不需要比较f和z
我认为这种方法可以归结为O(nlgn)的复杂性,因为按大小对数组进行排序将是O(nlgn),计算大小n*O(1)并进行内部基数排序O(n)。比较本身将是O(nlgn)(对此不太确定),因此总数将是O(nlgn)*2+2*O(n)=>O(nlgn)
树
这只是一个粗略的想法:您可以使用基数对所有数组进行排序,并将它们转换为Hemmington,然后用它们填充一棵树并遍历它,直到不再遍历会导致更小的距离。我不知道这有多高效
我觉得这是一种“蛮力式”的方法,虽然它确实有效,但我还是来询问是否有更好的方法。这本质上是一个线性扫描,超过几十万到一百万条条目的编辑成本可能相当高:本质上,越接近某种类似分治的方法越好。例如,我认为,如果输入数组是如上,我们就不需要考虑<代码>(‘x’,‘y’,‘z’’)/代码>或其他任何东西。这是我所能想到的,在这种情况下,我不确定你能比一般情况下有更好的性能,因为如果我们认为所有的数组都有相同大小的<代码> M < /代码>(不只是输入数组),那么<代码> O(n*m)是程序输入的大小,因此,一个更快的算法不可能存在(我们必须至少读取所有程序的输入)。但确实在某些特定情况下,您可能会实现一些技巧。如果您希望它运行得更快,您可以简单地并行化代码。上面的解决方案似乎可以利用哈明顿距离很好地工作,但这也可能是因为我对数据域有所了解。另一件事是,N已经在存储,一般排序的东西告诉我们一些关于数据结构的“修剪”一些意思,我们甚至不需要考虑它。我不确定是否会实现这一点,因此我来到这里。每个数组都可以存储为
[('a', 'f'), ('f'), ('a')]
function find_closest_arrays(A, B_1, ..., B_n) {
result = [0, ..., 0] // array of size n
for elem in A {
for i in 1 ... n {
if elem is in B_i {
result[i] ++
}
}
}
return result
}