[每日一题]74.搜索二维矩阵
74. 搜索二维矩阵 编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:
- 每行中的整数从左到右按升序排列。
- 每行的第一个整数大于前一行的最后一个整数。
举例:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3 输出:true
举例2:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13 输出:false
提示:
- m ==
matrix.length
- n ==
matrix[i].length
- 1 <= m, n <= 100
- -104 <=
matrix[i][j]
, target <= 104
Solutions
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
//暴力遍历
int m = matrix.length;
int n = matrix[0].length;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (matrix[i][j] == target){
return true;
}
}
}
return false;
}
}
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
//该方法还适用于每行元素数量不固定时
int m = matrix.length;
int n = matrix[0].length;
int left = 0;
int right = m - 1;
//创建变量记录所在行值,最后一个小于目标值的行
int row = 0;
//对第一列二分查找
//while不取等号避免左指针比右指针差一时left = mid陷入循环
while (left < right) {
//此处的+1是为避免left = mid时陷入循环
int mid = (right - left + 1) / 2 + left;
if (matrix[mid][0] == target) {
return true;
}
//赋left = mid为避免left一直右移而错过目标行
else if (matrix[mid][0] < target) {
left = mid;
row = left;
} else {
right = mid - 1;
}
}
//根据行值二分查找该行
left = 0;
right = n - 1;
while (left <= right) {
int mid = (right - left) / 2 + left;
if (matrix[row][mid] == target) {
return true;
} else if (matrix[row][mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return false;
}
}
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
//将二维矩阵看做一维
int m = matrix.length;
int n = matrix[0].length;
int left = 0;
int right = m * n - 1;
while (left <= right) {
int mid = (right - left) / 2 + left;
//根据mid值在一维数组中的位置推出该值在二维数组的行列
int row = mid / n;
int col = mid % n;
if (matrix[row][col] == target) {
return true;
} else if (matrix[row][col] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return false;
}
}
Ideas
- 方法一:两次二分查找
由于每行的第一个元素大于前一行的最后一个元素,且每行元素是升序的,所以每行的第一个元素大于前一行的第一个元素,因此矩阵第一列的元素是升序的。
我们可以对矩阵的第一列的元素二分查找,找到最后一个不大于目标值的元素,然后在该元素所在行中二分查找目标值是否存在。
- 方法二:一次二分查找
若将矩阵每一行拼接在上一行的末尾,则会得到一个升序数组,我们可以在该数组上二分找到目标元素。
代码实现时,可以二分升序数组的下标,将其映射到原矩阵的行和列上。