题目描述
写一个高效算法,在矩阵中查找一个数是否存在。矩阵有如下特点:
- 矩阵中每行的数,从左到右单调递增;
- 每行行首的数大于上一行行尾的数;
样例1
输入:
matrix = [
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
target = 3
输出: true
样例2
输入:
matrix = [
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
target = 13
输出:false
算法
(二分) $O(logn)$
我们可以想象把整个矩阵,按行展开成一个一维数组,那么这个一维数组单调递增,然后直接二分即可。
二分时可以通过整除和取模运算得到二维数组的坐标。
时间复杂度分析:二分的时间复杂度是 $O(logn^2) = O(logn)$。
C++ 代码
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
if (matrix.empty() || matrix[0].empty()) return false;
int n = matrix.size(), m = matrix[0].size();
int l = 0, r = n * m - 1;
while (l < r)
{
int mid = (l + r) / 2;
if (matrix[mid / m][mid % m] >= target) r = mid;
else l = mid + 1;
}
return matrix[r / m][r % m] == target;
}
};
可以先找他在第几行 在进行二分查找吗
这个check函数妙啊
其实用两个模板都ok,check决定了用哪个模板,如果check取matrix[mid / m][mid %m]>=target时,用第一个模板;check取matrix[mid / m][mid % m] <= target用第二个模板,不知道我的理解是否准确,灿哥的模板总结很到位,好好理解一下,慢慢找二分的做题感觉,一起加油哈!
两个模板都是可以的。不过决定用哪个模板完全由代码决定,和check的写法无关。如果代码写的是
r = mid
,那么计算mid
时不需要加1;如果代码写的是l = mid
,那么计算mid
时需要加1。多谢灿哥补充,其实我想表达的是check决定了代码是l=mid还是r=mid,进而决定用哪个模板,不知道灿哥跟我看法是否相同
check会影响写的是
l = mid
还是r = mid
,进而会影响mid
计算时需不需要加1,所以还是看l = mid
还是r = mid
,这才是本质。永远都分不清边界,什么时候 某数>target 什么时候 某数>=target ,什么时更新区间第一个模板,什么时候第二个模板,,,哭了,
这个左边界和右边界都是可以的
写 > 还是 >= 要根据题目来判断;如果更新方式写的是
r = mid; l = mid +1
用第一个模板;如果更新方式写的是l = mid; r = mid - 1
用第二个模板。我觉得y总的二分模版太厉害了,只要记住找的是满足条件的第一个元素,这样根据题目就知道是>还是>=
< <=
大佬牛逼
哈哈
yxcnb!
符合极简风格hhh
这个代码思想很棒,我还在对行二分,然后再对列二分。hh
哈哈思路很重要,不然代码会很长
+1hh