LeetCode | Search a 2D Matrix(二维矩阵中查找)


Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:

  • Integers in each row are sorted from left to right.
  • The first integer of each row is greater than the last integer of the previous row.

For example,

Consider the following matrix:

[
  [1,   3,  5,  7],
  [10, 11, 16, 20],
  [23, 30, 34, 50]
]

Given target = 3, return true.

题目解析:

这道题让我想起了《面试题3:二维数组中的查找》,不过那个题目中是行和列分别有序,跟这道还是有点区别的。


方案一:

利用剑指offer上的类似方法,行和列都变化,其效果不太好,跟先按顺序找行,再按照行一个一个找一样,甚至比这样还差,网上好多人用这个方法,也不知道怎么想的……

class Solution {
public:
    bool searchMatrix(vector<vector<int> > &matrix, int target) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (matrix.empty() || matrix[0].empty()) {
            return false;
        }
        int m = matrix.size(), n = matrix[0].size();
        int x = 0, y = n - 1; 
        while (0 <= x && x < m && 0 <= y && y < n) {
            if (matrix[x][y] == target) {
                return true;
            }
            else if (matrix[x][y] > target) {
                y--;
            }
            else {
                x++;
            }
        }
        return false;
    }
};

如果不存在的话,会一直找到循环不满足为止,如果按照顺序找,根据条件还能更快退出……


方案二:

由于列和行都有序,且上一行一定小于下一行。我们可以先按照每一行的第一个元素进行二分查找,能找的更好,找不到,返回target所在的行为止,然后在该行内二分查找。

class Solution {
public:
    bool searchMatrix(vector<vector<int> > &matrix, int target)
    {
        int low=0,high=matrix.size()-1;
        if(high==-1)return 0;
        int level=0;

        //if(matrix[0][0]>target)return false;

        while(low<=high)
        {
            level=(low+high)/2;
            if(matrix[level][0]==target)return true;
            if(matrix[level][0]>target)high=level-1;
            if(matrix[level][0]<target)
            {
                if(level==matrix.size()-1||matrix[level+1][0]>target)
                break;
                else low=level+1;
            } 
        }

        low=1,high=matrix[0].size()-1;
        int m;
        while(low<=high)
        {
            m=(low+high)/2;
            if(matrix[level][m]==target)return true;
            if(matrix[level][m]>target)high=m-1;
            if(matrix[level][m]<target)low=m+1;
        }
        return false;
    }
};

方案三:

由于二维数组在内存中按照行顺序排放,因此这道题可以按照整体二分查找来实现。计算机中的第 i 个在二维数组中的索引应该是 [ i / cols, i % cols],对,这样就对应起来了,我们就可以通过二分查找来操作。

这个方法很巧妙,也利用了数组的特性来查找。

class Solution {
public:
    bool searchMatrix(vector<vector<int> > &matrix, int target) {
      int rows = matrix.size();
      if(rows == 0) return false;
      int cols = matrix[0].size();
      //binary-search
      int low = 0, high = rows * cols - 1;
      while(low <= high)
      {
          int mid = (low + high) >> 1;
          if(matrix[mid/cols][mid%cols] < target)
          low = mid + 1;
          else if(matrix[mid/cols][mid%cols] > target)
          high = mid - 1;
          else
          return true;
      }
      return false;
    }
};




点赞