题目描述:
给你一个满足下述两条属性的 m x n 整数矩阵:
- 每行中的整数从左到右按非严格递增顺序排列。
- 每行的第一个整数大于前一行的最后一个整数。
给你一个整数 target ,如果 target 在矩阵中,返回 true ;否则,返回 false 。
示例 1:
输入: 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.lengthn == matrix[i].length1 <= m, n <= 100-10^4 <= matrix[i][j], target <= 10^4
思路:
我有点搞不清楚74和另一个210的区别是什么。 我首先想到的是Z形搜索。 后面又实现了二分查找,分别是纵向和横向两种情况的二分查找。
实现:
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
// return zSearch(matrix, target);
return bindarySearch(matrix, target);
}
private boolean zSearch(int[][] matrix, int target) {
int m = matrix.length, n = matrix[0].length;
int i = 0, j = n-1;
while (i < m && j >= 0) {
if (matrix[i][j] == target) {
return true;
}
if (matrix[i][j] > target) {
j--;
} else {
i++;
}
}
return false;
}
private boolean bindarySearch(int[][] matrix, int target) {
int m = matrix.length, n = matrix[0].length;
// find which row it should belows to, use the last column
int up = 0, down = m; // open right
int mid;
while (up < down) {
mid = (up + down) >> 1;
if (matrix[mid][n-1] == target) {
return true;
}
if (matrix[mid][n-1] < target) {
up = mid + 1;
} else {
down = mid; // open
}
}
if (up == m) {
return false;
}
int left = 0, right = n; // open
while (left < right) {
int mid2 = (left + right) >> 1;
if (matrix[up][mid2] == target) {
return true;
}
if (matrix[up][mid2] > target) {
right = mid2;
} else {
left = mid2 + 1;
}
}
return false;
}
}
复杂度分析:
方法一:zSearch(逐行/列搜索)
时间复杂度分析
该方法从矩阵的右上角开始,每一步要么向左移动一列(j--),要么向下移动一行(i++)。在最坏情况下(例如目标位于左下角或不存在),需要遍历最多 m + n 步。因此,时间复杂度为 O(m + n),其中 m 是行数,n 是列数。
空间复杂度分析
仅使用固定数量的变量(i, j, m, n),不依赖输入规模,因此空间复杂度为 O(1)。
方法二:binarySearch(二分查找)
时间复杂度分析
- 确定行:在最后一列进行二分查找,时间复杂度为 O(log m)。
- 确定列:在目标行进行二分查找,时间复杂度为 O(log n)。
总时间复杂度为 O(log m + log n),等价于 O(log(mn))。
空间复杂度分析
同样仅使用固定变量,空间复杂度为 O(1)。
对比总结
• zSearch 适合行列数接近的矩阵,但在大规模数据下效率较低。
• binarySearch 利用二分特性,时间复杂度显著更优,尤其适合大规模矩阵。
• 两者空间复杂度均为 O(1),无显著差异。