题目:
编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该矩阵具有以下特性:
- 每行的元素从左到右升序排列。
- 每列的元素从上到下升序排列。
示例:
现有矩阵 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
。
解题思路:
使用二分查找快速寻找数字所在的范围,有两个规律:
- 如果第一行的某个元素大于目标值,那么这个元素所在的列都大于目标值。
- 如果第一列的某个元素大于目标值,那么这一行所有的元素都大于目标值。
确定范围的行和列。
还有一种更简单的方法:
对于matrix[a][b]的元素,如果target大于该元素,说明这一整行的元素都不符合因为,行是排好序的,所以要移到下一行,同理,如果target小于该元素,说明这一整列元素都不符合,因为列也是排序的,所以要前移一列。这样就可以逐渐逼近近似值了。
时间复杂度O(m + n)。
代码实现:
class Solution { public boolean searchMatrix(int[][] matrix, int target) { if (matrix == null || matrix.length == 0|| matrix[0] == null || matrix[0].length == 0) return false; int rowStart = 0, rowEnd = matrix.length - 1; int colStart = 0, colEnd = matrix[0].length - 1; // 寻找行范围 while (rowStart <= rowEnd) { int mid = rowStart + (rowEnd - rowStart) / 2; if (matrix[mid][0] > target) rowEnd = mid - 1; else if (matrix[mid][0] == target) return true; else { if (mid == Integer.MAX_VALUE) break; rowStart = mid + 1; } } rowEnd = rowEnd < 0 ? 0 : rowEnd; // 寻找列范围 while (colStart <= colEnd) { int mid = colStart + (colEnd - colStart) / 2; if (matrix[0][mid] > target) colEnd = mid - 1; else if (matrix[0][mid] == target) return true; else { if (mid == Integer.MAX_VALUE) break; colStart = mid + 1; } } colEnd = colEnd < 0 ? 0 : colEnd; for (int i = rowEnd; i >= 0; i --) { for (int j = colEnd; j >= 0; j --) { if (matrix[i][j] == target) return true; } } return false; } }还有一种更简便的方法:
class Solution { public boolean searchMatrix(int[][] matrix, int target) { if(matrix == null || matrix.length < 1 || matrix[0].length <1) { return false; } int row = 0; int col = matrix[0].length - 1; while (row < matrix.length && col >= 0) { if (matrix[row][col] == target) return true; else if (matrix[row][col] > target) col --; else row ++; } return false; } }