class Solution {
public:
bool searchMatrix(vector<vector<int>> matrix, int target) {
// 1. 找到第一个"行首元素 > target"的行
auto row = upper_bound(
matrix.begin(),
matrix.end(),
target,
[](const int target, const vector<int>& currentRow) {
return target < currentRow[0];
}
);
// 如果第一行的行首元素就已经 > target
// 说明 target 比矩阵最小元素还小,不可能存在
if (row == matrix.begin()) {
return false;
}
// 2. 回退一行
// 这一行才是 target 可能存在的行
--row;
// 3. 在这一行中使用二分查找 target
return binary_search(row->begin(), row->end(), target);
}
};
这道题的思路可以总结为:
先利用每一行的第一个元素进行二分:
找第一个:
行首元素 > target
比如:
1 3 5 7
10 11 16 20
23 30 34 60
target = 16
行首元素是:
1 10 23
upper_bound 找到第一个大于 16 的行首元素:
23
因此 row 指向:
[23,30,34,60]
然后:
--row;
退回:
[10,11,16,20]
最后:
binary_search(...)
在这一行中继续二分查找 16。
所以整道题可以记成:
第一次二分确定 target 可能在哪一行,第二次二分在这一行里找 target。
时间复杂度:
找行:O(log m)
行内查找:O(log n)
总复杂度:O(log m + log n)
= O(log(m*n))
空间复杂度:
O(1)
另外更推荐函数参数写成引用:
bool searchMatrix(vector<vector<int>>& matrix, int target)
这样不会复制整个二维矩阵。