问题描述:
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:
Integers in each row are sorted in ascending from left to right.
Integers in each column are sorted in ascending from top to bottom.
每一行递增
每一列递增
(注意:没有说下一行一定比上一行大)
For example,
Consider the following matrix:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
Given target = 5, return true.
Given target = 20, return false.
问题求解:
方法一:利用分治法。跟Search a 2D Matrix中的方法二解法相同。
划分如下区域:
A B
* * * * | * * * *
* * * * | * * * *
* * * * | * * * *
* * * * | * * * *
-----------------------
* * * * | * * * *
* * * * | * * * *
* * * * | * * * *
* * * * | * * * *
C D
将中间元素center与target比较:
(1)center < target:排除A
(2)center > target:排除D
(3)center == target:return true.
时间复杂度:假设是n*n矩阵
T(nxn) = 3T(n/2 x n/2)得到T(nxn) = O(n^log3)
代码实现:
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int m=matrix.size(), n=matrix[0].size();
return find(matrix, 0, 0, m-1, n-1, target);
}
bool find(vector<vector<int>> &a, int x1, int y1, int x2, int y2, int target){
if ((x1>x2)||(y1>y2)){//矩阵为空
return false;
}
//计算中心点,横纵坐标分别取中值
int midx = (x1 + x2) >> 1;
int midy = (y1 + y2) >> 1;
if (a[midx][midy] == target){//恰好在中心点
return true;
}
else if (a[midx][midy] > target){//区域A+C||B
return find(a,x1,y1,midx-1,y2,target)||find(a,midx,y1,x2,midy-1,target);
}
else {//区域C+D||B
return find(a,x1,midy+1,x2,y2,target)||find(a,midx+1,y1,x2,midy,target);
}
}
};
方法二:与SearchIn2DMatrix方法一相同。时间复杂度O(m+n)
class Solution {
public:
//利用vector<vector<int>>& matrix表示二维整型数组
bool searchMatrix(vector<vector<int>>& matrix, int target) {
//m为数组行数,n为数组列数
int m=matrix.size(),n=matrix[0].size();
//从第一行最后一列开始,即从右上至左下进行
for(int row=0,col=n-1;(row<m)&&(col>=0);)
{
if(matrix[row][col]>target){
//最后一列没有用,删去
col--;
}
else if (matrix[row][col]<target){
//第一行没有用,删去
row++;
}
else{//相等的情况,说明已找到
return true;
}
}
//在循环外,说明把行列都删完后还未找到,则不存在
return false;
}
};