搜索二维矩阵
-
- [题解1 Z字查找(tricky)](#题解1 Z字查找(tricky))
- [题解2 一次二分查找](#题解2 一次二分查找)
- [题解3 两次二分查找](#题解3 两次二分查找)
给你一个满足下述两条属性的 m x n
整数矩阵:
每行中的整数从左到右按非严格递增顺序排列 。
每行的第一个整数大于前一行的最后一个整数。
给你一个整数 target
,如果 target
在矩阵中,返回 true
;否则,返回 false
。
提示:
m == matrix.length
n == matrix[i].length
1 <= m, n <= 100
- − 1 0 4 -10^4 −104 <=
matrix[i][j], target
<= 1 0 4 10^4 104
题解1 Z字查找(tricky)
cpp
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
// z字查找的思路,适用于每行有序、每列有序的情形
// 但这题的条件更强,即如果按行优先来看下标小的元素总是小于下标大的,直接二分会更快
int m = matrix.size(), n = matrix[0].size();
int r = 0, c = n-1;
while(r >= 0 && c >= 0 && r < m && c < n){
if(target > matrix[r][c]){
r ++;
}else if(target < matrix[r][c]){
c --;
}else return true;
}
return false;
}
};
题解2 一次二分查找
cpp
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int m = matrix.size(), n = matrix[0].size();
// 按行合并(torch.cat(dim = 0))
// 1234 2345 ...
int l = 0;
// 1D数组 尾下标
int r = m*n-1;
while(l <= r){
int mid = l + (r-l)/2;
// row = mid/n; column =mid%n
if(matrix[mid/n][mid%n] == target) return true;
else if(matrix[mid/n][mid%n] > target){
r = mid-1;
}else{
l = mid+1;
}
}
return false;
}
};
题解3 两次二分查找
cpp
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
// 从第一列找第一个大于target的下标 row
// 这么做是因为题目限制:每行的第一个整数大于前一行的最后一个整数
auto row = upper_bound(matrix.begin(), matrix.end(), target, [](const int b, const vector<int> &a) {
return b < a[0];
});
// 如果是第一行说明第一个数就大于target,整个matrix都大于target
if (row == matrix.begin()) {
return false;
}
// 上一行可能有target
--row;
// stl 二分
return binary_search(row->begin(), row->end(), target);
}
};