在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
示例:
现有矩阵 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。
给定 target = 20,返回 false。
解题思路
分析题目给出的条件——数组+有序,所以第一时间还是想到使用二分法来进行查找。
观察题目给出的条件,每一行都是从左到右的递增,每一列都是从上到下的递增。
-
如果从左上角出发

很明显,并不能确定target值大概在哪个方向,自然也不能用二分法来缩小查找的区间
-
如果从右上角出发
观察就能发现,如果从右上角向左下方向查找,刚好左边的值都比当前值小,右边的值都比当前值大,正好构成了一颗二叉查找树,现在使用二叉查找树的方式来遍历整个二维数组,时间复杂度为O(logN)
对角同理。
关键在于,从当前节点出发,需要满足一边递增、一边递减才能够使用二分法来缩小查找的区间
代码实现
从左上角出发
class Solution {
public boolean findNumberIn2DArray(int[][] matrix, int target) {
if (matrix.length == 0) return false;
int i = 0;
int j = matrix[0].length - 1;
while (i < matrix.length && j >= 0) {
if (matrix[i][j] == target) return true;
if (matrix[i][j] < target) {
i++;
} else {
j--;
}
}
return false;
}
}
总结: 关键还是在于要理解二分法的本质,即通过不断缩小查找的区间来实现高效的查找。