查找排序矩阵(mXn)中的某个值,时间复杂度为O(lgm)+ O(lgn)

时间:2012-05-16 21:58:12

标签: search matrix

矩阵A按行和列排序,其中A [i] [j]< A [i] [j + 1]和A [i] [j]< A [I + 1] [j]的。 另外一个信息是每行的第一个元素小于前一行的最后一个元素,例如:

⎡1  3   5  17⎤
⎢2  4   6  18⎥
⎣7  9  11  20⎦

我对这些额外信息在确定O(lgn)复杂性方面的作用感到困惑。

我可以提出O(m)+ O(n)如下:

int search(int mat[4][4], int n, int x)
{
   int i = 0, j = n-1;  //set indexes for top right element
   while ( i < n && j >= 0 )
   {
       if ( mat[i][j] == x )
       {
          printf("\n Found at %d, %d", i, j);
          return 1;
       }
       if ( mat[i][j] > x )
           j--;
       else //  if mat[i][j] < x
           i++;
       }

       printf("\n Element not found");
       return 0;  // if ( i==n || j== -1 )
  }

但我认为我没有使用过这些信息:每行的第一个元素小于前一行的最后一个元素

有人可以给我一些提示吗?另外这不是功课。谢谢!

1 个答案:

答案 0 :(得分:1)

您目前正在做的是详尽的搜索(即检查每个元素一次),因此O(n * m)。您没有利用矩阵的排序特性。

给定排序列表,Binary Search允许您在O(lg n)中搜索。基本上,您检查列表的中间元素。如果它大于你的目标那么你知道你可以忽略列表的后半部分。重复此过程,每次搜索空间的一半,直到找到元素或搜索空间等于1项。在Python代码中:

import math

def binSearch(value, data):
    bottom = 0 #first entry
    top = len(data) -1 #last entry

    while bottom <= top: #if bottom ever becomes greater than top then the object is not in the list
        i = int(bottom + math.floor((top - bottom)/2)) #find the mid-point
        if data[i] == value: #we found it
            return i
        elif data[i] > value:
            top = i - 1 #value must be before i
        else:
            bottom = i + 1 #value must be after i

    return None #not found

现在,考虑一下您可以从矩阵结构中收集哪些信息。您知道给定n x m矩阵mat按照您的描述排序,对于任何行imat[i][0]是行中的最低项,mat[i][n]是最高的。同样,对于任何列j,mat[0][j]是该列的最低值,mat[m][j]是最高值。这意味着如果mat[i][0] <= value <= mat[i][n]不为真,那么值不能在第i行。同样,如果mat[0][j] <= value <= mat[m][j]不为真,那么值不能在第j列中。

因此,显而易见的改进是,对于可能包含该值的每一行,进行二进制搜索。

for row in mat:
    if (row[0] <= value) AND (row[len(row) - 1] >= value): #if the value could possibly be in the row
        result = binSearch(value, row)

        if result: #if we found it
            return result

binSearch()是O(lg m)。最糟糕的情况是每行都执行binSearch(),因此O(n * lg m)。

我试图实现一个O(lg n * lg m)解决方案,但我无法弄明白。问题是我只能消除矩阵的左上角和右下角。我无法消除左下角或右上角。