题目描述
写出一个高效的算法来搜索 m × n矩阵中的值。
这个矩阵具有以下特性:
每行中的整数从左到右是排序的。
每行的第一个数大于上一行的最后一个整数。
样例
考虑下列矩阵:
[
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
给出 target = 3,返回 true
挑战
O(log(n) + log(m)) 时间复杂度
分析
因为是有序的,所以直接看每个小列表的最后一个是不是小于这个数就知道在不在这个小列表里了。
代码
class Solution {
public:
/*
* @param matrix: matrix, a list of lists of integers
* @param target: An integer
* @return: a boolean, indicate whether matrix contains target
*/
bool searchMatrix(vector<vector<int>> &matrix, int target) {
// write your code here
for(vector<int> i : matrix) {
if(i.back() >= target) {
for(int j : i) {
if(j == target) return true;
}
}
}
return false;
}
};
优化
根据挑战的提示:时间复杂度为O(log(n) + log(m)),即O(logMN)。再根据题目中所说的行列均有序可以发现使用两次二分法查找并且没有重复元素。不过需要注意外层二分法条件与正常不同,代码如下:
class Solution {
public:
/*
* @param matrix: matrix, a list of lists of integers
* @param target: An integer
* @return: a boolean, indicate whether matrix contains target
*/
bool searchMatrix(vector<vector<int>> &matrix, int target) {
// write your code here
int nlow = 0, nhigh = matrix.size() - 1;
while(nlow <= nhigh) {
int nmid = nlow + (nhigh - nlow) / 2;
if(matrix[nmid][matrix[nmid].size() - 1] < target) {
nlow = nmid + 1;
} else if(matrix[nmid][0] > target) {
nhigh = nmid - 1;
} else {
int mlow = 0, mhigh = matrix[nmid].size() - 1;
while(mlow <= mhigh) {
int mmid = mlow + (mhigh - mlow) / 2;
if(matrix[nmid][mmid] < target) {
mlow = mmid + 1;
} else if(matrix[nmid][mmid] > target) {
mhigh = mmid - 1;
} else {
return true;
}
}
return false;
}
}
return false;
}
};
总结
二分法时间复杂度为O(logN).