leetcode链接:剑指 Offer 04. 二维数组中的查找
题目描述
在一个 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。
限制:
0 <= n <= 1000
0 <= m <= 1000
解题思路
方法一:双层for循环暴力查找,时间复杂度:O(n*m)空间复杂度:O(1),简单但不推荐。
方法二:使用二分法查找,先找行再找列,时间复杂度:O(nlogm)空间复杂度:O(1)。
方法三:根据题目条件“从左到右递增,从上到下递增”,我们可以从左下角或右上角的元素开始进行与target对比,以左下角 matrix[n-1][0] 为例:在相同列中, matrix[n-1][0] 大于其上方的元素值,在相同行中, matrix[n-1][0] 小于其右侧的元素值,如果target大于 matrix[n-1][0] ,那么我们就从左下角右移一格成 matrix[n-1][0+1] 继续与target对比,如果target小于 matrix[n-1][0] ,那么我们就从左下角上移一格成 matrix[n-1-1][0] 继续与target对比,若找到target,则返回 true ,反之则返回 false ,右上角同理可得。时间复杂度:O(n+m)空间复杂度:O(1),为最优解,推荐使用这种方法。
代码实现
class Solution {
public boolean findNumberIn2DArray(int[][] matrix, int target) {
// 矩阵若空或行数、列数为0,直接返回false
if(matrix == null || matrix.length == 0 || matrix[0].length == 0){
return false;
}
// 读取出矩阵的行数与列数
int rows = matrix.length;
int columns = matrix[0].length;
// 确定左下角的坐标
int row = rows -1;
int col = 0;
while(row >=0 && col < columns){
if(matrix[row][col] > target){
row--; // 从左下角上移一格
}else if(matrix[row][col] < target){
col++; // 从左下角右移一格
}else{
return true;
}
}
return false;
}
}
我的思考
想要高效地解决这道题,我们需要破除惯性思维,遇到矩阵我们不一定要从 matrix[0][0] 开始处理,我们应该结合题目条件找到其特性,根据特性研究其可行解。
通过这道题我对矩阵有了更深的理解尤其是对如下矩阵的理解:
| int[][] matrix | matrix == null | matrix.length | matrix[0].length |
|---|---|---|---|
| [] | false | 0 | ArrayIndexOutOfBoundsException |
| [[]] | false | 1 | 0 |
| [[],[]] | false | 2 | 0 |
所以在上述代码实现中,因为会出现矩阵形式为"[]"的测试用例,所以需要先判断,再读取矩阵的行数与列数,否则会报错"ArrayIndexOutOfBoundsException"
// 矩阵若空或行数、列数为0,直接返回false
if(matrix == null || matrix.length == 0 || matrix[0].length == 0){
return false;
}
// 读取出矩阵的行数与列数
int rows = matrix.length;
int columns = matrix[0].length;
此文章是我的第二篇刷题总结,比较基础,希望能和大家一起学习,我也会努力更新《剑指offer》其他题目,加油!