思路:我们可以发现,每个任意大小的矩形,都是右下角的元素最大,左上角的元素最小,这就是一个区间。我们可以以这种思路去搜索。把每个要搜的元素跟对角线元素先比较,然后在两个对角线顶点间的矩形中去寻找。
大错特错!这样是区分不开的,也很难找,因为你右下角往左往上移动,martix都变小,没有区分度,何谈寻找?左上角同理:往右往下移动,martix值都变大,没有区分度,谈何寻找?
!!!!!我们把目光放到右上角和左下角就会发现新大陆:
对于右上角元素:往左比他小,往下比他大。
对于左下角元素:往上变小,往右变大,是有区分度的?
这性质像不像二叉搜索树?????
这个题一般是两种方法:
法一:二分查找O(mlogn)
首先先来学习一个C++ algorithm库里的函数:lower_bound
lower_bound
是 C++ 标准模板库(STL)中的一个函数,位于 <algorithm>
头文件中。它是基于二分查找实现的。
功能:lower_bound
用于在一个已排序的范围内查找第一个不小于 给定值的元素。它返回一个迭代器,指向该元素。如果所有元素都小于目标值,则返回 end()
迭代器。
lower_bound
的实现是基于二分查找 算法,因此时间复杂度为**O(log n)
** ,其中 n
是范围内的元素数量。由于它要求输入的范围是已排序的,所以可以通过逐步缩小范围来高效地找到目标值的位置。
对每一行使用二分进行查找,看是否在这一行里。(因为该题是每一行升序的有序排列)
代码:
cpp
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int m=matrix.size();
int n=matrix[0].size();
for(int i=0;i<m;i++)
{
auto t=lower_bound(matrix[i].begin(),matrix[i].end(),target);//返回指向该行不小于target的第一个元素的一个迭代器
if(t!=matrix[i].end()&&*t==target) return true;
}
return false;
}
};
法二:Z字型查找 O(n+m)
这个查找方法就是用我开头说的右上角和左下角的性质。
cpp
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int m=matrix.size()-1;
int n=matrix[0].size()-1;
int x=0,y=n;
while(x<=m&&y>=0)//从右上角往左下角搜索,当前值大于目标值 y--,小于目标值则X++;
{
if(matrix[x][y]==target)
{
return true;
}
if(matrix[x][y]>target)
{
y--;
}
else x++;
}
return false;
}
};
可以看到最坏情况是 要查找的元素在整个矩阵的左下角,这个时候所花时间为(m+n)。故时间复杂度为O(m+n)。