【问题标题】:Want to know Time Complexity while using Binary Search logic for Sorted Matrix想知道使用二分搜索逻辑的排序矩阵时的时间复杂度
【发布时间】:2014-07-15 13:42:07
【问题描述】:

我一直在寻找对排序矩阵使用二分搜索逻辑的最佳优化方式。

使用 Stack Over flow 中“Michal Sznajder”建议的逻辑。 Most efficient way to search a sorted matrix?

但是具有递归关系的计算时间复杂度有困难。 谁能帮帮我。

虽然我使用的是二分搜索逻辑,但我认为它不是 T(n) = log (m + n)。

是 T(n) = log (log ( log (m x n))) 还是 log ( log (m x n)) ?

代码可能不是最好的标准或优化,但我刚开始写。

/*
 1,    4,      7,      10,     13,
 2,    5,      8,      11,     14,
 3,    6,      9,      12,     15,
 16,   17,     18,     19,     20,
 21,   22,     23,     24,     25,
 26,   27,     28,     29,     30

 a ..... b ..... c
 . .     . .     .
 .   1   .   2   .
 .     . .     . .
 d ..... e ..... f
 . .     . .     .
 .   3   .   4   .
 .     . .     . .
 g ..... h ..... i

a, c, g < i --> if not there is no element 

a, b, d < e
b, c, e < f
d, e, g < h
e, f, h < i

Left Top    :   Right Top
-----------Mid--------------
Left Bottom :   Right Bottom

*/

public int SearchSortedMatrixInLogNByM(int[,] SortedMatix, int elementToSearch, int rowStPos, int colStPos, int rowEndPos, int colEndPos)
{
    // Step 0. Check for basic validations.
    if (SortedMatix == null)
    {
        throw new Exception("Matrix is empty");
    }

    // Step 1. Use divide and conquer and to get the middle element.
    int resultNode = 0;
    int rowMidPos = (rowStPos + rowEndPos) / 2;
    int colMidPos = (colStPos + colEndPos) / 2;

    // Step 2. Mid element in Recursive Sub Matrix. For e.g in above example if it is 'e', 'f','h','i' then found.
    if (SortedMatix[rowMidPos, colMidPos] == elementToSearch || SortedMatix[rowMidPos, colEndPos] == elementToSearch ||
        SortedMatix[rowEndPos, colMidPos] == elementToSearch || SortedMatix[rowEndPos, colEndPos] == elementToSearch)
    {
        return elementToSearch;
    }

    // Step 3. Terminate the sub matrix iteration when the element is not found in the 2 X 2 matrix. 
    if ((rowStPos == rowMidPos || colStPos == colMidPos) && SortedMatix[rowStPos, colStPos] != elementToSearch)
    {
        return 0;
    }

    // Step 4. Left Top Sub Matrix.
    if (resultNode == 0 && elementToSearch < SortedMatix[rowMidPos, colMidPos])
    {
        resultNode = SearchSortedMatrixInLogNByM(SortedMatix, elementToSearch, rowStPos, colStPos, rowMidPos, colMidPos);
    }

    // Step 5. Right Top Sub Matrix.
    if (resultNode == 0 && elementToSearch < SortedMatix[rowMidPos, colEndPos])
    {
        resultNode = SearchSortedMatrixInLogNByM(SortedMatix, elementToSearch, rowStPos, colMidPos, rowMidPos, colEndPos);
    }

    // Step 6. Left bottom Sub Matrix.
    if (resultNode == 0 && elementToSearch < SortedMatix[rowEndPos, colMidPos])
    {
        resultNode = SearchSortedMatrixInLogNByM(SortedMatix, elementToSearch, rowMidPos, colStPos, rowEndPos, colMidPos);
    }

    // Step 7. Right bottom Sub Matrix.
    if (resultNode == 0 && elementToSearch < SortedMatix[rowEndPos, colEndPos])
    {
        resultNode = SearchSortedMatrixInLogNByM(SortedMatix, elementToSearch, rowMidPos, colMidPos, rowEndPos, colEndPos);
    }

    return resultNode;
}

public void SearchSortedMatrixTest()
{
    int[,] SortedMatix = {{ 1,    4,      7,      10,     13,},
                            { 2,    5,      8,      11,     14,},
                            { 3,    6,      9,      12,     15,},
                            { 16,   17,     18,     19,     20,},
                            { 21,   22,     23,     24,     25,},
                            { 26,   27,     28,     29,     30}};

    //SearchSortedMatrixInNLogN(AssendMatix, 21);

    StringBuilder strBldr = new StringBuilder();

    strBldr.Append("\n 1  : " + SearchSortedMatrixInLogNByM(SortedMatix, 1, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 2  : " + SearchSortedMatrixInLogNByM(SortedMatix, 2, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 3  : " + SearchSortedMatrixInLogNByM(SortedMatix, 3, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 4  : " + SearchSortedMatrixInLogNByM(SortedMatix, 4, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 5  : " + SearchSortedMatrixInLogNByM(SortedMatix, 5, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 6  : " + SearchSortedMatrixInLogNByM(SortedMatix, 6, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 7  : " + SearchSortedMatrixInLogNByM(SortedMatix, 7, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 8  : " + SearchSortedMatrixInLogNByM(SortedMatix, 8, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 9  : " + SearchSortedMatrixInLogNByM(SortedMatix, 9, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 10 : " + SearchSortedMatrixInLogNByM(SortedMatix, 10, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));

    strBldr.Append("\n 11 : " + SearchSortedMatrixInLogNByM(SortedMatix, 11, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 12 : " + SearchSortedMatrixInLogNByM(SortedMatix, 12, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 13 : " + SearchSortedMatrixInLogNByM(SortedMatix, 13, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 14 : " + SearchSortedMatrixInLogNByM(SortedMatix, 14, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 15 : " + SearchSortedMatrixInLogNByM(SortedMatix, 15, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 16 : " + SearchSortedMatrixInLogNByM(SortedMatix, 16, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 17 : " + SearchSortedMatrixInLogNByM(SortedMatix, 17, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 18 : " + SearchSortedMatrixInLogNByM(SortedMatix, 18, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 19 : " + SearchSortedMatrixInLogNByM(SortedMatix, 19, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 20 : " + SearchSortedMatrixInLogNByM(SortedMatix, 20, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));

    strBldr.Append("\n 21 : " + SearchSortedMatrixInLogNByM(SortedMatix, 21, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 22 : " + SearchSortedMatrixInLogNByM(SortedMatix, 22, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 23 : " + SearchSortedMatrixInLogNByM(SortedMatix, 23, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 24 : " + SearchSortedMatrixInLogNByM(SortedMatix, 24, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 25 : " + SearchSortedMatrixInLogNByM(SortedMatix, 25, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 26 : " + SearchSortedMatrixInLogNByM(SortedMatix, 26, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 27 : " + SearchSortedMatrixInLogNByM(SortedMatix, 27, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 28 : " + SearchSortedMatrixInLogNByM(SortedMatix, 28, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 29 : " + SearchSortedMatrixInLogNByM(SortedMatix, 29, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 30 : " + SearchSortedMatrixInLogNByM(SortedMatix, 30, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));

    strBldr.Append("\n\n Example 2:\n");

    SortedMatix = new int[,] {{ 1,    4,      7,},
                                { 2,    5,      8,},
                                { 3,    6,      9}};

    strBldr.Append("\n 1  : " + SearchSortedMatrixInLogNByM(SortedMatix, 1, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 2  : " + SearchSortedMatrixInLogNByM(SortedMatix, 2, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 3  : " + SearchSortedMatrixInLogNByM(SortedMatix, 3, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 4  : " + SearchSortedMatrixInLogNByM(SortedMatix, 4, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 5  : " + SearchSortedMatrixInLogNByM(SortedMatix, 5, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 6  : " + SearchSortedMatrixInLogNByM(SortedMatix, 6, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 7  : " + SearchSortedMatrixInLogNByM(SortedMatix, 7, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 8  : " + SearchSortedMatrixInLogNByM(SortedMatix, 8, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));
    strBldr.Append("\n 9  : " + SearchSortedMatrixInLogNByM(SortedMatix, 9, 0, 0, SortedMatix.GetLength(0) - 1, SortedMatix.GetLength(1) - 1));

    MessageBox.Show("Element(s) Search in Sorted Matrix and the result(s) are " + strBldr.ToString());          
}

【问题讨论】:

  • 在询问时间复杂度之前,请确保算法正确。是的,针对stackoverflow.com/questions/4137986/… 发布了一个算法,但该答案上的 cmets 表明该算法不完整。在某些情况下它会给出错误的答案。
  • 是的,大卫。我阅读了那些 cmets,并且在我的逻辑中注意了一些条件。也许我可以在我的描述中提到这一点。例如。我正在检查 resultNode 不为零以进行另一个子矩阵递归调用。在大多数条件下进行了测试,但未在此处发布所有条件。我尚未考虑优化的一点来自我的例如如果我在子矩阵 (1,4,2,5) 中查找 3,它将首先与 1,2,4 进行比较,因为 3 小于 5。如果 (1,4,2) 会进行更多不必要的检查,5) 和 3 在大约 X 百万矩阵中的十万行。感谢您强调。
  • 我们很多人都知道的一个最简单的方法是,如果矩阵是 n(列)X m(行)并且 n > m。然后对 m(行)线性重复循环并在 n(列)上应用二进制搜索。所以这将是 O(m log n)。但我正在努力。

标签: algorithm recursion data-structures matrix recursive-datastructures


【解决方案1】:

更新:在网络的帮助下,我能够稍微改进上一个答案。

事实证明,与许多问题一样,这个问题很容易通过良好的 Google 搜索解决(只要它可以解决)。我尝试了“按行和列排序的搜索矩阵”。结果之一是这个页面:

Find number in sorted matrix (Rows n Columns) in O(log n)

坏消息是,在最坏的情况下,你不能比一个简单的一次一行算法做得更好,即 O(min(m,n) * log(max(m ,n)))。另一方面,朴素算法很容易实现,并且(我认为)在一个恒定的最优因子内。

对该问题的解决方案的评论链接到一个页面,该页面包含一些额外的有用材料,http://twistedoakstudios.com/blog/Post5365_searching-a-sorted-matrix-faster,它似乎概述了一个有用的、不那么天真的算法。我不认为我能做得比这更好;肯定不容易。

对于它的价值,这是我之前的回答:

算法需要工作。考虑这个 4x4 矩阵:

 1,  2,  4, 10
 3,  6,  7, 12
 5,  8,  9, 14
11, 13, 15, 16

考虑在此矩阵中搜索包含值 9、10 或 11 的单元格。所有这三个值都通过了“测试”以位于子矩阵 2(右上角)中,但它们也都通过了位于子矩阵中的测试3(左下)。事实上,其中一个在子矩阵 2 中,一个在子矩阵 3 中,一个不在这两个子矩阵中。根据包含值 4、12、13 和 16 的单元格的观察值,对于这三个数字中的任何一个,您唯一能说的就是这些数字都不在子矩阵 1 中。所以你消除了 1/4该步骤的矩阵。

根据算法,值 4 和 5 应该出现在子矩阵 1 中(因为每个都小于 6,在该子矩阵的右下角),但实际上一个在子矩阵 2 中,另一个在子矩阵 3。当您要查找的值小于子矩阵 1 的右下角元素时,这四个比较通常不允许您消除 任何 个子矩阵。

【讨论】:

  • 我同意你的观点,大卫,是的,上面提到的主要 cmets 关于从你的示例中搜索 4 的类似示例之一。顺便问一下,你有没有想过重写算法的最佳方法?如果不是一些线索也应该与时间复杂度一起提供帮助。谢谢。
  • @LearningBee :我确实找到了一些可能有帮助的附加信息。我已将其添加到上面的答案中。
  • 感谢您的时间和链接大卫,我也遇到了堆栈溢出链接但被忽略了。感谢您的帮助。
【解决方案2】:

如果我对算法的理解正确,您将使用 Z 模式将矩阵划分为四个象限,然后通过递归检查象限的中心并知道接下来要查看其四个子象限中的哪一个来进行查询。

在这种情况下,您可以将其视为类似于每个节点有四个子节点的树结构。每次评估当前节点时,您将进入四个子节点之一。查询此类树结构(以及此数据结构)中节点位置的时间为 O(log base 4 (n)),其中 n 是矩阵中元素的总数。

这样做的原因是因为这是树的高度,我们必须在树的每一层上只停留一次才能找到最有可能在底部的元素,因为树的该层包含 ~75%整个树中的节点。

当然,这是一个方阵。随着矩阵变得更加矩形,您的搜索效率会降低,最坏的情况是 n x 1 的矩阵,这将是一条长线。在这种情况下,您会看到 O(log base 2 (n)),因为您实际上每次只在两个子节点之间进行拆分。

【讨论】:

  • 哇,感谢您的快速响应和关于树的好例子。很高兴知道这一点。你能以同样简单的方式帮助我计算递归关系吗?
  • 我对 Recurrence Relation 这个词不熟悉,你到底在找什么?
  • 没那么快!请参阅我对主要问题的评论。
  • 我没有足够的“声誉点”来评论 David K 在下面的回答,但问题是他的示例不再满足 Z 模式,因此无法通过此方法搜索.又名Morton Order
  • 我在任何一个问题陈述中都没有看到任何提及 Z 模式的内容。仅仅是列和行分别满足排序条件。而且,我什至不是指出原始算法缺陷的人。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多