搜索m / n的二维数组中的元素,即行和列

时间:2013-08-04 17:33:45

标签: c++ c algorithm search

您将获得一个MxN的2D数组,该数组按行和列顺序排序。搜索元素的有效方法是什么?

3 个答案:

答案 0 :(得分:5)

从矩阵的右上角位置v开始。如果它是您正在寻找的项目x,那么您已经完成了。如果v小于您要查找的项目,请向下移动。如果v大于您要查找的项目,请向左移动。重复,直到你到达矩阵的末端。

正确性证明:

如果右上角的项目等于x,则无需证明。考虑两种情况

v < x

在这种情况下,我们知道顶行中所有元素都小于x。因此,我们可以忽略整个顶行并将向下移动

因此,我们可以从

开始
  1 2 3 4 5 6
1 * * * * * v
2 * * * * * *
3 * * * * * * 
4 * * * * * *
5 * * * * * *

  1 2 3 4 5 6
1 . . . . . .
2 * * * * * v
3 * * * * * * 
4 * * * * * *
5 * * * * * *

也就是说,我们最终遇到了一个小问题。

另一种情况是

v > x

在这种情况下,我们知道右列中所有元素都大于x。因此,我们可以忽略整个右列并移动 left

  1 2 3 4 5 6
1 * * * * * v
2 * * * * * *
3 * * * * * * 
4 * * * * * *
5 * * * * * *

  1 2 3 4 5 6
1 * * * * v .
2 * * * * * .
3 * * * * * .
4 * * * * * .
5 * * * * * .

同样,我们最终遇到了一个小问题。通过归纳,我们完成了。该算法具有时间复杂度O(m + n)

编辑:

Ted Hopp链接到这个想法的绝对美妙的扩展,提供更好的性能。

这是个主意。在我上面给出的算法中,我们的想法是我们可以一次性排除整个行或列。他链接的想法是消除整个象限。这个想法很简单

* * * * * *
* * * * * *
* * * * * * <- binary search
* * * * * *
* * * * * *

二进制搜索中间行。这将为您提供项目,或包含您正在寻找的项目的位置

* * * * * *
* * * * * *
* * * a|b * <- x between a, b
* * * * * *
* * * * * *

现在,这是关键的洞察力。整个左上象限和整个右下象限可以立即消除;左上角的所有元素都小于a,右下角的所有元素都大于b

. . . . * *
. . . . * *
. . . a|b .
* * * * . .
* * * * . .

现在递归剩下的两件作品。此外,您可以在中间行或左上角到右下角度执行相同的操作,具体取决于哪个将产生最大增益。

答案 1 :(得分:2)

有一个非常好的写入here算法来解决这个问题。正如文章所描述的那样,对每一行(或每个列同样)按行进行简单的二进制搜索,得到O(n log n)解。但是,从右上角开始然后线性向左或向下行进的简单算法会产生O(n)算法。 (这是正确的:线性搜索胜过二分搜索!)然而,更好的结果来自于使用矩阵的二进制分区(基于线性搜索)并产生一种算法,在某些情况下具有O((log n) 2 )(次线性)表现。

最好的算法似乎是一种分而治之的方法:对于 m × n 矩阵 M n (列数)&lt; m (行数) * 和目标值 v ,搜索中间行(称为行 r )对于索引 c ,使 M r c v &lt;目标值 v M r c +1 。如果 v = M r c ,那么您就完成了。否则,递归地将算法应用于子矩阵 M r + 1,0 ... M m -1, c M 0, c +1 ... M n -1, r 。 (这些是由单元格界定的左下角矩阵( r +1, c )和由单元格界定的右上角矩阵( r -1, c +1)。)

有关性能和代码本身的详细信息,请参阅链接。

* 如果 n &gt; m ,搜索中间列。如果 n = m ,请搜索对角线。在每种情况下,子矩阵的确切边界需要从上面的描述中稍微调整一下;看文章。

答案 2 :(得分:0)

通常第一个索引是“row”,第二个索引是“column”,列索引应该是连续的内存,即使行是以不同的块分配的,所以从这个角度看,搜索所有内容的速度应该更快一行的列,然后移动到下一行并在那里迭代列。

显然,假设您搜索的所有项目均匀分布,并且“每行中的第一项更可能是您正在寻找的候选项,并且每列最后一项最不可能”。

同样非常明显的是,如果每一行都包含已排序的值,那么您可以对列进行二进制搜索,如果最小值和最大值未覆盖您正在搜索的范围,则跳过整行。

与“更快”的所有内容一样,您确实需要对解决方案进行基准测试,以确定在您的特定情况下哪种方法最佳。