Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 这个搜索算法是最优的吗?_Algorithm_Language Agnostic_Optimization_Search - Fatal编程技术网

Algorithm 这个搜索算法是最优的吗?

Algorithm 这个搜索算法是最优的吗?,algorithm,language-agnostic,optimization,search,Algorithm,Language Agnostic,Optimization,Search,我有两个列表,L和M,每个列表包含数千个64位无符号整数。我需要找出L的任意两个成员之和是否本身就是M的一个成员 是否有可能改进以下算法的性能 Sort(M) for i = 0 to Length(L) for j = i + 1 to Length(L) BinarySearch(M, L[i] + L[j]) 您可以通过使用哈希表(排序M数组除外)来避免二进制搜索。您可以通过使用哈希表(排序M数组除外)来避免二进制搜索。您可以通过使用哈希表(排序M数组除外)来代替

我有两个列表,L和M,每个列表包含数千个64位无符号整数。我需要找出L的任意两个成员之和是否本身就是M的一个成员

是否有可能改进以下算法的性能

Sort(M)
for i = 0 to Length(L)
    for j = i + 1 to Length(L)
        BinarySearch(M, L[i] + L[j])

您可以通过使用哈希表(排序M数组除外)来避免二进制搜索。

您可以通过使用哈希表(排序M数组除外)来避免二进制搜索。

您可以通过使用哈希表(排序M数组除外)来代替排序
M
n*log(n)
为代价,创建一个哈希集


您还可以在迭代时将所有和存储在另一个哈希集中,并添加检查以确保不执行两次相同的搜索。

您可以创建哈希集,而不是以
n*log(n)
为代价对
M
进行排序


您还可以在迭代时将所有和存储在另一个哈希集中,并添加一个检查,以确保不会执行两次相同的搜索。

或者,将L的所有成员添加到哈希集lSet,然后在M上迭代,对M中的每个M执行以下步骤:

  • 将m添加到hashset mSet-如果m已经在mSet中,则跳过此迭代;如果m在hashset dSet中,也跳过此迭代
  • 从m中减去l小于m的每个成员l,得到d,并测试d是否也在lSet中
  • 如果是,则将(l,d)添加到某个集合rSet中;将d添加到hashset数据集

  • 这将需要更少的迭代次数,但需要更多的内存。如果要提高速度,您需要为结构预先分配内存。

    或者,将L的所有成员添加到hashset lSet,然后在M上迭代,对M中的每个M执行以下步骤:

  • 将m添加到hashset mSet-如果m已经在mSet中,则跳过此迭代;如果m在hashset dSet中,也跳过此迭代
  • 从m中减去l小于m的每个成员l,得到d,并测试d是否也在lSet中
  • 如果是,则将(l,d)添加到某个集合rSet中;将d添加到hashset数据集

  • 这将需要更少的迭代次数,但需要更多的内存。如果要提高速度,您需要为结构预先分配内存。

    问题中示例代码的复杂性是O(m log m+l2 log m),其中l=| l |和m=| m |,因为它对l(O(l2))中的每一对元素运行二进制搜索(O(log m)),m首先排序

    假设哈希表插入和查找是O(1)操作,用哈希表替换二进制搜索将复杂性降低到O(l2)


    这是渐近最优的,只要你假设你需要处理列表L上的每一对数字,因为有O(l2)这样的对。如果L上有几千个数字,它们是随机的64位整数,那么您肯定需要处理所有对。

    问题中示例代码的复杂性是O(m log m+l2 log m),其中L=| L |和m=| m |,因为它对L(O(l2))中的每一对元素运行二进制搜索(O(log m)),m首先排序

    假设哈希表插入和查找是O(1)操作,用哈希表替换二进制搜索将复杂性降低到O(l2)

    这是渐近最优的,只要你假设你需要处理列表L上的每一对数字,因为有O(l2)这样的对。如果L上有几千个数字,它们是随机的64位整数,那么您肯定需要处理所有的对。

    (我假设您的目标是找到L中的所有对,它们的总和等于m)

    忘记哈希表吧

    对两个列表进行排序

    然后做算法的外循环:遍历L中的每一个元素i,然后遍历L中的每一个较大的元素j。这样,形成和,检查它是否在M中

    但不要使用二进制搜索:只需从上次查看的位置进行线性扫描。假设你在处理一些值i,你有一些值j,后面跟着一些值j’。当搜索(i+j)时,您将到达M中找到该值的点,或者第一个最大值。你现在正在寻找(i+j');因为j'>j,你知道(i+j')>(i+j),所以它在M中不可能比你得到的最后一个位置更早。如果L和M都是平滑分布的,那么很有可能在M中找到(i+j')的点只差一点点

    如果阵列分布不平滑,那么比线性扫描更好的可能是某种跳跃扫描——一次向前看N个元素,如果跳跃太远,则将N减半

    我相信这个算法是O(n^2),它和任何提出的散列算法一样快(有一个O(1)基元运算,但仍然要做O(n**2)。这也意味着你不必担心O(n log n)排序。它比散列算法具有更好的数据局部性——它基本上由阵列上的成对流式读取组成,重复n次


    编辑:我编写了Paul Baker的原始算法、Nick Larsen的哈希表算法和我的算法的实现,以及一个简单的基准测试框架。实现很简单(哈希表中的线性探测,线性搜索中没有跳过),我不得不猜测各种大小参数。有关代码,请参阅。我欢迎对任何实现、框架和参数的更正或建议

    对于分别包含3438个项目的L和M,其值范围为1到34380,且Larsen哈希表的负载系数为0.75,则运行的中值时间为:

    • 贝克(二进制搜索):423716646ns
    • 拉森(哈希表):733 479 121纳秒
    • 安德森(线性搜索):62077597纳秒
    差异比我预期的要大得多(我承认,这与我预期的方向不符)。我怀疑我在实施过程中犯了一个或多个重大错误。如果有人发现一个,我真的希望