「前端刷题」74. 搜索二维矩阵

161 阅读1分钟

「这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战」。

题目

链接:leetcode-cn.com/problems/se…

编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:

  • 每行中的整数从左到右按升序排列。
  • 每行的第一个整数大于前一行的最后一个整数。

 

示例 1:

输入: matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3 输出: true

示例 2:

输入: matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13 输出: false

 

提示:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 100
  • -104 <= matrix[i][j], target <= 104

解题思路

思路1

  1. 从矩阵左上角开始遍历,等于直接跳出,小于向左走一步n--,大于下走一步m++
  2. 循环后依旧执行1的操作,直到m,n不符合循环条件

代码

/**
 * @param {number[][]} matrix
 * @param {number} target
 * @return {boolean}
 */
var searchMatrix = function(matrix, target) {
      if(matrix.length === 0) return false
      let m = 0, n = matrix[0].length -1
      // 1.从矩阵左上角开始遍历,等于直接跳出,小于向左走一步,大于下走一步
      // 2.循环后依旧执行1的操作
      while(m <= (matrix.length - 1)&& n>=0){
          if(matrix[m][n] === target) return true
          else if(target < matrix[m][n]){
              n--
          }else{
              m++
          }
      }
      return false
};

思路2

矩阵已经排好序了 左下角的位置特殊:上面的比它小,右边的比它大 选取左下角的位置开始遍历,如果当前数大了,上移一行;当前数小了,右移一列 找到返回true,遍历完返回false

代码

const searchMatrix = (matrix, target) => {
    // 矩阵的行、列
    const [m, n] = [matrix.length, matrix[0].length];
    // (i,j)初始位置在左下角
    let [i, j] = [m - 1, 0];
    // 一直遍历到右上角位置
    while (i >= 0 && j <= n - 1) {
        if (matrix[i][j] > target) {
            // 太大了,上移一行
            i--;
        } else if (matrix[i][j] < target) {
            // 太小了,右移一列
            j++;
        } else {
            // 找到,返回true
            return true;
        }
    }
    // 遍历完没找到,返回false
    return false;
};

思路3

如果我们能把二维数组打平成一维数组,那就是套个二分法模板的事

剩下的问题是,怎么从一维数组的下标逆推二维数组的坐标?其实就是简单的数学计算。

我们将二维数组中的数字从左到右、从上到下,标记为第 0~(m x n) 个数字,用 pos 来表示。那么 pos 与数字在二维矩阵中坐标的关系如下:

x: floor(pos / cols)
y: pos % cols
  • pos: 第 n 个数字
  • cols: 二维矩阵的列数

代码

/**
 * @param {number[][]} matrix
 * @param {number} target
 * @return {boolean}
 */
var searchMatrix = function (matrix, target) {
    if (!matrix || !matrix.length) return false;

    const rows = matrix.length;
    const cols = matrix[0].length;
    let l = 0,
        r = rows * cols - 1,
        mid = 0;

    while (l <= r) {
        mid = ((l + r) / 2) << 0;
        const [x, y] = getCoordFromPos(mid);
        const num = matrix[x][y];
        if (num < target) l = mid + 1;
        else if (num > target) r = mid - 1;
        else return true;
    }

    return false;

    // *************************************
    function getCoordFromPos(pos) {
        const x = (pos / cols) << 0;
        const y = pos % cols;
        return [x, y];
    }
};