【问题标题】:Fastest Search algorithm in 2D array二维数组中最快的搜索算法
【发布时间】:2018-04-13 01:12:54
【问题描述】:

所以,我有一个二维数组,int a[X][Y]; X 可以达到10 000 000Y 最大6。 给定一个数组 int v[Z] (Z ),我必须查看是否在 a 中找到包含来自 v 的所有元素的行。

对于这个问题,最快的算法是什么?你将如何实现它?

我已经尝试过经典的逐行搜索,然后用fors搜索2个,一个用于v元素,一个用于a元素,但耗时太长。

最好(最快)的方法是什么?

int check()
{
    int nrfound;

    for (int l = 0; l < lines_counter; l++) for each line in a array
    {
        nrfound = 0;

        for (int i = 0; i < n; i++) { // for each element in v array

            for (int j = 0; j < m; j++) // for each element in a[l] line
                if (v[i] == a[l][j])
                    nrfound++;
            if (nrfound == Z)
                return 0;
        }
    }
    return 1;
}

【问题讨论】:

  • @EugeneSh.: 你在想a[X] == v吗?因为问题似乎是在询问 a[X] 是否是 v 的超集...
  • 您也可以将工作拆分为几个线程。
  • 你应该发布你的代码,也许有一些微优化会很有帮助,但你错过了它们。当您经验不足时,通常会发生这种情况。
  • “最快的算法” --> 最坏的情况,或者平均来说有很宽的 `int 范围?
  • 我立即看到了改进,而不是计算值的数量是否相等,而是在第一个不相等的值上中止。

标签: c algorithm search


【解决方案1】:

如果a[i][] 子数组中有重复元素,则您的算法存在缺陷。 v 的匹配元素将被多次计数,并且计数可能恰好等于 Z

这是一个更正的版本:

int check(int X, int Y, int Z, int a[X][Y], int v[Z]) {
    for (int x = 0; x < X; x++) {
        // for each line in array a
        int mask = 0;
        for (int z = 0; z < Z; z++) {
            // for each element in array v
            for (int y = 0, m = 1; y < Y; y++, m <<= 1) {
                // for each element in line a[x]
                if (v[z] == a[x][y] && !(mask & m)) {
                    mask |= m;
                    break;
                }
            }
            if (y == Y)
                break;
        }
        if (z == Z)
            return 0;   // found a match
        }
    }
    return 1;   // no match
}

不幸的是,上面的代码可能比发布的代码还要慢,但值得测试,因为一旦在a[x] 中找不到来自v 的元素,就会退出内部循环。

【讨论】:

    【解决方案2】:

    当您使用 C 时,它会限制可用的数据结构: 我建议:

    • 初始化 N 个线程,将矩阵行 X 划分为 N 个桶,然后并行搜索每个桶。
    • 取决于 2D 输入数组的类型:您可以通过边界条件节省一些时间,因为您希望查询数组的所有元素保持顺序。你也可以利用每行的(Z

    • 对数组进行排序会增加复杂性。所以最好避免它。

    【讨论】:

      【解决方案3】:

      我认为需要考虑三件事:

      • 使用线程。
      • 如果可能,在构造int a[X][Y] 表时,我将创建额外的数组int[6][Y],其中将包含:
        • 包含 1、2、3 .. 6 个元素的索引列表。这使您可以缩小搜索范围。
      • 对于每个 X 计数的哈希值。然后计算 V 值的 Hash。
        • 比较哈希码,而不是每个单独的值。

      【讨论】:

      • 因此,对于 [N][M] 数组,最好的排序方法是什么? N = 100 000 000,M = 6。排序这个数组的最快算法是什么? (我需要每行的元素保持在一起)用 C 语言实现会很棒。
      【解决方案4】:

      对于同一个数组a[]与多个不同的v[]复用的情况:

      将a[][]的每一行排序为预备步骤(执行一次)

      排序 v[]

      使用单个循环(而不是两个)来获得有序 v[] 和 a[] 的每个有序行的交集 - 使用类似于 merge 合并排序过程的方法

      index_v = 0
      index_a = 0
      while index_v < length_v and index_a < length_a:
         if v[index_v] == a[index_a]
             index_v++, index_a++
         else if v[index_v] < a[index_a]
             index_v++   
         else
           index_a++
      if index_v == length_v:
         return OK, a[] line contains all v elements
      

      【讨论】:

      • 因此,对于 [N][M] 数组,最好的排序方法是什么? N = 100 000 000,M = 6。排序这个数组的最快算法是什么? (我需要每行的元素保持在一起)用 C 语言实现会很棒。
      • 对长度为 6 的行进行排序?任何方法,例如 - 插入排序。具体长度有一些特殊的方法,但它们更复杂,不会带来显着的收益。
      【解决方案5】:

      使用固定排序网络可以轻松地对大小为 6 的 1e7 数组进行排序,无论是否使用 Simd/多线程。

      v进行排序,并将其与合并排序两个排序列表的原理进行比较。

      总体最坏情况复杂度在 13e7..24e7 比较之间(6 个元素的排序网络需要 12 次条件交换,合并 v/a[n] 需要 1..12 次比较。

      【讨论】:

      • 能否详细介绍一下固定排序网络的算法,以及与合并排序两个排序列表的原理进行比较? :D
      • 因此,对于 [N][M] 数组,最好的排序方法是什么? N = 100 000 000,M = 6。排序这个数组的最快算法是什么? (我需要每行的元素保持在一起)用 C 语言实现会很棒。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-10-29
      • 2019-01-27
      • 1970-01-01
      • 2017-10-29
      • 2021-11-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多