74. Search a 2D Matrix
Leetcode Array Binary SearchWrite an efficient algorithm that searches for a value in an m \times n matrix. This matrix has the following properties:
- Integers in each row are sorted from left to right.
- The first integer of each row is greater than the last integer of the previous row.
Example 1:
Input:
matrix = [
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
target = 3
Output: true
Example 2:
Input:
matrix = [
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
target = 13
Output: false
分析¶
看到这道题目的时候,看到搜索,首先联想到是二分法。但是一般情况下,使用二分法的对象是一维数组,这里的二维数组怎么处理呢?一种直接的想法就是,首先找到目标所在的行,然后找到所在的列。时间复杂度是O(\log(m) + \log(n))。过程中需要特别注意出现空数组([[ ]]
, [ ]
)的情况。
public boolean searchMatrix(int[][] matrix, int target) {
int m = matrix.length;
if (m == 0) return false;
int n = matrix[0].length;
if (n == 0) return false;
//find row
int row;
int lo = 0, hi = m - 1;
while (lo <= hi) {
int mid = (hi + lo) >>> 1;
int cmp = matrix[mid][n - 1] - target;
if (cmp > 0) hi = mid - 1;
else if (cmp < 0) lo = mid + 1;
else return true;
}
row = lo;
// check row
if (row > m - 1) return false;
//find column
int col;
lo = 0; hi = n - 1;
while (lo <= hi) {
int mid = (hi + lo) >>> 1;
int cmp = matrix[row][mid] - target;
if (cmp > 0) hi = mid - 1;
else if (cmp < 0) lo = mid + 1;
else return true;
}
col = lo - 1;
return false;
}
但是这种写法,真的有点复杂,而且非常容易出错,反正我写的过程中出现了不少小的错误。有没有更简单、更直接的方法呢?当然是有的!直接把二维数组看成是一维数组,唯一需要变动的是lo
, hi
和下标的处理:
int lo = 0;
int hi = m * n - 1;
int mid = (lo + hi) >>> 1;
// access
matrix[mid/n][mid%n]
完整的代码如下:
它的算法复杂度和第一种方案一样,也是O(\log(mn)).
public boolean searchMatrix(int[][] matrix, int target) {
int m = matrix.length;
if (m == 0) return false;
int n = matrix[0].length;
if (n == 0) return false;
int lo = 0, hi = m*n - 1;
while (lo <= hi) {
int mid = (lo + hi) >>> 1;
int cmp = matrix[mid/n][mid%n] - target;
if (cmp > 0) hi = mid - 1;
else if (cmp < 0) lo = mid + 1;
else return true;
}
return false;
}