排序矩阵查找

分治

  1. 解题思路:

    • 使用分治法,先比较目标与矩阵对角线元素,找到元素返回 true,找不到则分解;
    • 步骤一 分解:矩阵被划分成 4个 子问题:可以看到绿色部分一定小于目标元素;红色部分一定大于目标元素;只需在剩下的两个行列升序的矩阵中寻找目标元素;
    • 步骤二 子问题分别求解:子问题元素个数为 0 或者最小元素大于目标返回 false;否则对两个子矩阵继续递归分解;
    • 步骤三 合并: 任一子矩阵内寻找到目标元素,则返回 true;
  2. 复杂度:

    • 时间复杂度:O((m+n)*log(m+n));从矩阵左上方开始不断比较目标值与对角线元素,寻找划分位置;如果未找到目标值,接着继续在两个子矩阵重复这个过程(递归);
    • 空间复杂度:O(log(m+n));需常数级临时变量;递归调用占用额外空间,递归深度为log(m+n);
  3. 代码实现:

    var searchMatrix = function (matrix, target) {
      let row = matrix.length;
      if (row === 0) return false;
    
      let col = matrix[0].length;
      if (col === 0) return false;
    
      return searchSubMatrix(matrix, target, 0, 0, row - 1, col - 1);
    };
    
    function searchSubMatrix(matrix, target, startRow, startColumn, endRow, endColumn) {
      // 1.结束条件:
      //    元素个数小于1
      //    矩阵最小元素大于目标值(所有元素都大于目标值)
      if (startRow > endRow || startColumn > endColumn || matrix[startRow][startColumn] > target) return false;
    
      // 对角线元素个数
      let diagonalLen = Math.min(endRow - startRow + 1, endColumn - startColumn + 1);
      // 在对角线上查找元素、分解问题、递归求解、合并
      for (let i = 0; i < diagonalLen; i++) {
        if (matrix[startRow + i][startColumn + i] === target) return true;
        // 当找到对角线最后 或者 下一个对角线的值大于 target
        if (i === diagonalLen - 1 || matrix[startRow + i + 1][startColumn + i + 1] > target) {
          // 找到了分界点,寻找 4 个区域中的剩下两个(右上、左下)
          return searchSubMatrix(matrix, target, startRow, startColumn + i + 1, startRow + i, endColumn)
              || searchSubMatrix(matrix, target, startRow + i + 1, startColumn, endRow, startColumn + i);
        }
      }
    
      return false;
    }
    

双指针

  1. 解题思路:

    • 从矩阵右上方元素开始,比较当前元素与目标值的大小;
    • 若当前元素等于目标值,那么返回 true;
    • 若当前元素小于目标值,那么当前元素左侧的元素都会小于目标值,指针下移;
    • 若当前元素大于目标值,那么当前元素右下方的元素都会大于目标值,指针左移;
    • 若指针在矩阵外,返回 false;
  2. 复杂度:

    • 时间复杂度:O(m+n),最多比较 m+n-1 次;
    • 空间复杂度:O(1),空间消耗方面只需常数级临时变量;
  3. 代码实现:

    var searchMatrix = function (matrix, target) {
      let row = matrix.length;
      if (row === 0) return false;
    
      let col = matrix[0].length;
      if (col === 0) return false;
    
      // 初始位置为右上角的元素
      let currentRow = 0, currentColumn = col - 1;
      while (currentColumn >= 0 && currentRow < row) {
        // 当前元素等于target
        if (matrix[currentRow][currentColumn] === target) return true;
        if (matrix[currentRow][currentColumn] < target) {
          // 当前元素小于target,指针下移
          currentRow++;
        } else {
          // 当前元素大于target,指针左移
          currentColumn--;
        }
      }
    
      return false;
    };
    
打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. 排序矩阵查找
  2. 2. 分治
  3. 3. 双指针