在排序矩阵中查找元素

2022-09-03 09:10:05

问题:给定一个矩阵,其中对每行和每列进行排序,请编写一个方法来查找其中的元素。

这是一个经典的面试问题,这是我的解决方案

boolean F(int[][] matrix, int hs, int he, int ws, int we)
{
    if (hs > he || ws > we) 
        return false; 

    int m = (hs + he) / 2; 
    int n = (ws + we) / 2;

    if (matrix[m][n] == t)
    {
        return true;
    }
    else if (matrix[m][n] < t)
    {
        // find the ele in the same row, right to [m][n]
        F(m, m, n + 1, we);

        // find the ele in the same col, upper to [m][n]
        F(m + 1, he, n, n);

        // find the ele in the area, where i>m,j>n 
        F(m + 1, he, n + 1, we);       
    } 
    else if (matrix[m][n] > t)
    {
        // very similar to previous part
    }
}

该算法的运行时间为 log(m) + log(n)。我正在寻找一种更有效的算法,或者使用简洁的代码。

有了更多的评论,我想出了以下代码:

// return target recurrence in the matrix
int F(int[][] m, int rs, int re, int cs, int ce, int t){
   int r1 = rs, r2 = re;
   int c1 = cs, c2 = ce;
   int r=0 , c = c1;

   while( r1 < r2 && c1 < c2 ){
   // find the last element that <= t in column c
     r  = FlastLess( r1, r2, c, t)

     if( r == -1 ) break;

     else{
       // find the first ele in the row that is >=t
       c = FfirstGreater( r, c1, c2, t);

       if( c == -1)  break;
       else{
         r2 = r; 
         c1 = c; 
       }// else    
     }// else 
   }// while
}// f

下面是函数 F1 和 F2 的链接 查找排序数组中大于目标的第一个元素

void FlastLess(int s, int e, int t){
  int l = s, h = e;
  while( l != h ){
     int mid = (l+h)/2;
     if( mid >=  t) high = mid - 1; 
     else {
       if( high < t) low= mid + 1;
       else low = mid;
     } 
  }

 void FfirstGreater(int s, int e, int t){
  while(l < h){
    mid = (l+h)/2;
    if ( mid <=  t) low = mid+1;
    else high = mid;
  }
 }

}

答案 1

从矩阵的左下角开始。然后转到右侧,直到找到确切的数字(完成),或者直到找到一个更大的数字。

然后你在矩阵中向上走,直到你找到确切的数字(完成),或者直到你找到一个太小的数字。

然后你再次向右移动,...依此类推,直到找到数字或直到到达矩阵的右侧或顶部。

下图包含一些示例,使用 Excel 表以绿色显示目标编号,以黄色显示后面的路径。

enter image description here

enter image description here

在最后一个示例中,我们查找 207,它不在矩阵中:

enter image description here

这只是算法。编码留给你作为练习:-)

编辑:从最底层的行开始时,二进制搜索可能会提供更好的起点。对于算法的其余部分,这可能无关紧要。


答案 2

你的算法可能是O(log m + log n),但它也给出了错误的答案。

假设您在以下矩阵中搜索“4”(其中左上角是 row=0,col=0):

0 1 4
1 2 5
2 3 6

您的算法从查看中心开始。由于 大于 ,因此继续搜索同一行(不存在)、同一列(不在那里)和右下角(不在那里)。哎 呦。242

对每行和每列进行排序的约束实际上非常弱。特别是,沿对角线的元素可以是任何顺序的。

我认为正确的方法是对第一列和最后一列进行二进制搜索,以缩小可能的行的范围。然后对这些行中的第一行和最后一行执行二进制搜索,以缩小可能的列的范围。等等。

不知道如何分析这个的性能...