题目内容
基本描述
编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:(1)每行中的整数从左到右按升序排列;(2) 每行的第一个整数大于前一行的最后一个整数。
实例
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
输出:true
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13
输出:false
算法求解-一次二分查找
思路
将每一行进行顺序拼接,可以得到一个升序数组,然后使用二分查找。代码实现时,可以二分升序数组的下标,将其映射到原矩阵的行和列上。
代码
public boolean searchMatrix(int[][] matrix, int target) {
int m = matrix.length, n = matrix[0].length;
int low = 0, high = m * n - 1;
while (low <= high){
int mid = (high-low)/2 + low;
int x = matrix[mid/n][mid%n];
if (x > target){
high = mid - 1;
}else if (x < target){
low = mid + 1;
}else {
return true;
}
}
return false;
}
复杂度分析
时间复杂度:二分法,为
O
(
l
o
g
m
n
)
O(log\ mn)
O(log mn),其中m和n分别是矩阵的行数和列数。
空间复杂度:只使用了mid、low和high三个参数,为
O
(
1
)
O(1)
O(1)。
算法求解-两次二分查找
思路
第一列是升序的;同时每行也是升序的。所以可以先查找在哪一行,然后再查找在该行的哪一列,两次查找都使用二分法。查找在哪一行时,针对第一行进行查找,寻找最后一个不大于target的位置。
代码
public boolean searchMatrix(int[][] matrix, int target) {
int rowIndex = binarySearchFirstColumn(matrix, target);
if (rowIndex == -1){
return false;
}
return binarySearchRow(matrix[rowIndex], target);
}
public int binarySearchFirstColumn(int[][] matrix, int target){
int low = -1, high = matrix.length - 1;
while (low < high){
int mid = (high-low+1)/2 + low;
if (matrix[mid][0] <= target){
low = mid;
}else {
high = mid - 1;
}
}
return low;
}
public boolean binarySearchRow(int[] row, int target){
int low = 0, high = row.length - 1;
while (low <= high){
int mid = (high-low)/2 + low;
if (row[mid] < target){
low = mid + 1;
}else if (row[mid] > target){
high = mid - 1;
}else {
return true;
}
}
return false;
}
复杂度分析
时间复杂度:两次二分,为
O
(
l
o
g
m
+
l
o
g
n
)
=
O
(
l
o
g
m
n
)
O(log\ m+log\ n) = O(log\ mn)
O(log m+log n)=O(log mn),其中m和n分别是矩阵的行数和列数。
空间复杂度:
O
(
1
)
O(1)
O(1)。