74. 搜索二维矩阵
题目介绍
编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:
每行中的整数从左到右按升序排列。
每行的第一个整数大于前一行的最后一个整数。
示例 1:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
输出:true
示例 2:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13
输出:false
提示:
m == matrix.length
n == matrix[i].length
1 <= m, n <= 100
-104 <= matrix[i][j], target <= 104
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/search-a-2d-matrix
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
贪心算法
先向下搜索,查看target应该属于哪一行;
之后对该行向右搜索,查看是否有target值。
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
// 先找目标值属于哪一行
int i, j=0;
int m=matrix.size(), n=matrix[0].size();
for(i=0; i<m-1; i++) //属于第i行
{
if(matrix[i+1][0]>target)
{
break;
}
}
while(j<n)
{
if(matrix[i][j]==target) return true;
else if(matrix[i][j]<target)
{
j++;
}
else{ //未找到
return false;
}
}
return false;
}
};
时间复杂度为 O ( m + n ) O(m+n) O(m+n)
两次二分查找
对于向下搜索和向右搜索,都是一个有序数组查找的问题,因为可以用二分查找来优化。
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int i;
int m=matrix.size(), n=matrix[0].size();
// 先找目标值属于哪一行
int left=0, right=m-1, mid;
while(left<=right)
{
mid = (left+right)/2;
if(matrix[mid][0]==target) return true;
else if(matrix[mid][0] > target) right = mid-1;
else left = mid+1;
}
i = right; //属于第i行
if(i<0) //防止出现所有数都大于target i=-1的情况
{
return false;
}
left = 0, right = n-1;
// 查看第i行的元素
while(left<=right)
{
mid = (left+right)/2;
if(matrix[i][mid]==target) return true;
else if(matrix[i][mid] > target) right = mid-1;
else left = mid+1;
}
return false;
}
};
时间复杂度为 O ( l o g m + l o g n ) = O ( l o g m n ) O(logm+logn)=O(logmn) O(logm+logn)=O(logmn)
一次二分查找
再次观察,我们可以发现这个二维数组按行排列之后可以变成一个一维有序数组。因此我们可以假设 A [ i ] [ j ] = B [ k ] A[i][j] = B[k] A[i][j]=B[k] 的一个有序数组,使用一次二分查找即可。
则 i = k / n , j = k i = k/n, j=k%n i=k/n,j=k,其中 n 为列的长度。
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int m=matrix.size(), n=matrix[0].size();
int left=0, right=m*n-1, mid;
while(left<=right)
{
mid = (left+right)/2;
if(matrix[mid/n][mid%n]==target) return true;
else if(matrix[mid/n][mid%n] > target) right = mid-1;
else left = mid+1;
}
return false;
}
};
时间复杂度为 O ( l o g m n ) O(logmn) O(logmn)