题目:
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 from left to right.
- The first integer of each row is greater than the last integer of the previous row.
For example,
Consider the following matrix:
[ [1, 3, 5, 7], [10, 11, 16, 20], [23, 30, 34, 50] ]
Given target = 3
, return true
.
思路:
1、二分查找法:这道题目中的数组其实就是把一维有序数组变成二维了而已。因此思路也可以有两种:
1)把二维数组映射到一维上,然后直接采用一维数组的标准二分查找法,映射函数是f(i, j) = i * n + j。这种思路的时间复杂度是O(log(m*n)),其中m和n分别表示二维数组的行个数和列个数。
2)直接在二维数组上执行两次查找:首先利用二分查找找到target所在的行,然后在该行中再执行二分查找找到target的值。该方法的时间复杂度是O(logm+logn) = O(log(m*n)),其实和上面的相同。
2、阶梯查找法:(我自己想出来的蹩脚名字)思路是从二维数组的最右端开始查找,如果target小于该数组元素,则target要是存在则一定在该数组元素的左侧;否则target一定位于该数组元素的下侧或者左下侧。这种做法的时间复杂度是O(m+n),其中m和n分别代表数组的行个数和列个数。
代码:
1、二分查找法:
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
if(matrix.size() == 0 || matrix[0].size() == 0)
return false;
int m = matrix.size(), n = matrix[0].size();
return searchMatrix(matrix, target, m, n, 0, m * n - 1);
}
private:
bool searchMatrix(const vector<vector<int>> &matrix,
int target, int m, int n, int low, int high) {
while(low <= high) {
int mid = (low + high) / 2;
int value = matrix[mid / n][mid - mid / n * n];
if(value == target)
return true;
else if(target < value)
high = mid - 1;
else
low = mid + 1;
}
return false;
}
};
2、阶梯查找法:
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
if(matrix.size() == 0)
return false;
int i = 0, j = matrix[0].size() -1;
while(i < matrix.size() && j >= 0)
{
if(matrix[i][j] == target)
return true;
else if(matrix[i][j] > target)
j--;
else if(matrix[i][j] < target)
i++;
}
return false;
}
};