题目

题目来源:力扣(LeetCode

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:
每行的元素从左到右升序排列。
每列的元素从上到下升序排列。

示例 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

思路分析

数组从左到右和从上到下都是升序的,如果从右上角出发开始遍历呢?
会发现每次都是向左数字会变小,向下数字会变大,有点和二分查找树相似。二分查找树的话,是向左数字变小,向右数字变大。

所以我们可以把 target 和当前值比较。

如果 target 的值大于当前值,那么就向下走一行。
如果 target 的值小于当前值,那么就向左走一列。
如果相等的话,直接返回 true 。
也可以换个角度思考。

如果 target 的值小于当前值,也就意味着当前值所在的列肯定不会存在 target 了,可以把当前列去掉,从新的右上角的值开始遍历。

同理,如果 target 的值大于当前值,也就意味着当前值所在的行肯定不会存在 target 了,可以把当前行去掉,从新的右上角的值开始遍历。

我们来看最特殊的两个值,右上角15,左下角18。如果 target 大于15,因为第一行的最大值就是15,证明 target 一定不在第一行,所以我们当前位置往下移动一行找;如果 target 小于 15,15是最后一列的最小值,证明 target 不在最后一列 上,target 往左移动一列找。

  1. var searchMatrix = function (matrix, target) {
  2. // 行
  3. let row = 0;
  4. // 列
  5. let col = matrix[0].length - 1;
  6. // 从右上角开始遍历
  7. while (row < matrix.length && col >= 0) {
  8. // row, col 等于待查找值
  9. if (matrix[row][col] == target) return true;
  10. // 从右上角开始遍历,如果当前值小于目标值,意味着当前值所在的行很定不会存在目标值了,向下移动一行,列不变,即 matrix[row][col] 变成 matrix[row + 1][col],继续进行比较
  11. if (matrix[row][col] < target) row += 1;
  12. // 从右上角开始遍历,如果当前值大于目标值,意味着当前值所在的列很定不会存在目标值了,向下移动一列,行不变,即 matrix[row][col] 变成 matrix[row][col - 1],继续进行比较
  13. else col -= 1;
  14. }
  15. return false;
  16. };