LeetCode热题(JS版) - 240. 搜索二维矩阵 II

92 阅读2分钟

题目描述

编写一个高效的算法来搜索mxn矩阵中的一个目标值,该矩阵具有以下特性:

  • 每行升序排列。
  • 每列升序排列。

示例1:

image.png 输入:

matrix = [
  [1,   4,  7, 11, 15],
  [2,   5,  8, 12, 19],
  [3,   6,  9, 16, 22],
  [10, 13, 14, 17, 24],
  [18, 21, 23, 26, 30]
], target = 5

输出:true

示例2:

image.png 输入:

matrix = [
  [1,   4,  7, 11, 15],
  [2,   5,  8, 12, 19],
  [3,   6,  9, 16, 22],
  [10, 13, 14, 17, 24],
  [18, 21, 23, 26, 30]
], target = 20

输出:false

思路

本题可以采用二分查找算法来求解。由于矩阵每行都是升序排列的,每列也是升序排列的,因此我们可以先在第一列中进行二分查找。如果找到了目标值,则直接返回true;否则,我们可以在目标值可能存在的行中进行二分查找,最后判断目标值是否存在即可。

先在第一列二分查找原因:找到第一个大于等于目标值的元素所在行,然后在该行进行线性搜索。这样可以避免很多不必要的搜索,提高算法效率。

代码实现

function searchMatrix(matrix: number[][], target: number): boolean {
  const m = matrix.length;
  if (m === 0) {
    return false;
  }
  const n = matrix[0].length;

  let left = 0,
    right = m - 1;
  // 在第一列中进行二分查找
  while (left <= right) {
    const mid = Math.floor((left + right) / 2);
    if (matrix[mid][0] === target) {
      return true;
    } else if (matrix[mid][0] > target) {
      right = mid - 1;
    } else {
      left = mid + 1;
    }
  }

  // 在目标值可能存在的行中进行二分查找
  for (let i = 0; i < left; i++) {
    let l = 0,
      r = n - 1;
    while (l <= r) {
      const mid = Math.floor((l + r) / 2);
      if (matrix[i][mid] === target) {
        return true;
      } else if (matrix[i][mid] > target) {
        r = mid - 1;
      } else {
        l = mid + 1;
      }
    }
  }

  // 未找到目标值
  return false;
}

image.png

复杂度分析

  • 时间复杂度为 O(nlogm)O(n\log m),其中 nnmm 分别为矩阵的行数和列数。因为需要在第一列中进行一次二分查找,时间复杂度为 O(logm)O(\log m);每列中进行最多一次二分查找,总时间复杂度为 O(nlogm)O(n\log m)

  • 空间复杂度为 O(1)O(1),因为只使用了常数个额外变量。