查找第一个元素的个数不小于第二个元素的向量对

时间:2019-06-24 21:07:10

标签: algorithm time-complexity

这是How to compare each element in two arrays with time complexity less than O(n^2)的概括。假设我们有两个矩阵A和B,其大小分别为nxk和mxk,分别可寻址为A[row][col]B[row][col]。如果每个(i, j)r都允许一对A[i][r] >= B[j][r]。有什么方法可以比天真的O(nmk)更快地识别每个可接受的对

for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
        bool accept = true;
        for (int r = 0; r < k && accept; ++r) {
            accept &= (A[i][r] >= B[j][r]);
        }
        if (accept) { std::cout << i << ", " << j << "\n"; }
    }
}

如果k = 1,那么我可以使用链接的问题隐含的解决方案在n log n次内完成任务。但是,当k> 1时,由于诸如此类的矩阵而变得更加困难:

A[0] = {1, 1}
A[1] = {3, 1}
A[2] = {3, 5}
A[3] = {5, 3}
A[4] = {5, 5}

B[0] = {2, 4}
B[1] = {4, 2}

可接受的对是(2,0),(4,0),(3,1)和(4,1)。按第一个元素排序给出上面的顺序,其中B = 1可接受的是连续的(A = 3和A = 4),而B = 0可接受的不是。类似地,按第二个元素排序使B = 0可接受的内容连续,而B = 1可接受的内容不连续。一遍排序和读取类似k = 1解决方案的连续范围似乎不起作用。

我要考虑的特定设置的n和m大约为数百万,而k大约为一千,所以nmk时间不是很实用。

1 个答案:

答案 0 :(得分:0)

输出大小可以为nm,因此该算法的性能不能超过O(nm)。当然,可以提高平均水平,但在很大程度上取决于您的数据和分布。以下是一些通用提示:

如果您负担得起m * k内存,则可以保留按第一列值排序的B索引的排序列表。第二列相同,依此类推。通过这种结构+二进制搜索,您可以回答给定固定列c和固定数x的问题,即O(log m)中有多少B [j] [c] <= x。

然后对于A [i]中的每个值x,您可以检查有多少B [j] [c] <= x。按此数量对它们进行排序。第一个值(将其称为L1)将是最小的数字,因此您将通过该列与排序列表中的B进行比较。通过使用二进制搜索,您可以跳过开头,仅与B的L1数组进行比较。

您可以按照从B [j] [c] <= x计算中保留的顺序进行比较,而不必以任何顺序逐列进行比较。这将意味着我们从A使用的第二个值相对于其余列低于B中的列的机会最小。这将有助于最大程度地减少对不满足条件的对的比较。 >