- Search a 2D Matrix
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.
Example
Consider the following matrix:
[
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
Given target = 3, return true.
Challenge
O(log(n) + log(m)) time
解法1:两次Binary Search。第1次找到相应Row, 第2次在Row里面找target。
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) {
int nRow = matrix.size();
if (nRow == 0) return false;
int nCol = matrix[0].size();
if ((target < matrix[0][0]) || (target > matrix[nRow - 1][nCol - 1])) return false;
vector<int> col0(nRow, 0);
for (int i = 0; i < nRow; ++i) {
col0[i] = matrix[i][0];
}
int indexRow = binarySearch(col0, 0, nRow - 1, target);
int indexCol = binarySearch(matrix[indexRow], 0, nCol - 1, target);
if (target == matrix[indexRow][indexCol]) return true;
else return false;
}
// find the index of the first element that is smaller or equal to target
int binarySearch(vector<int> nums, int start, int end, int target) {
if (nums.size() == 0 || start > end) return -1;
while (start + 1 < end) {
int mid = start + (end - start) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
start = mid;
} else {
end = mid;
}
}
if (nums[start] == target) return start;
if (nums[end] == target) return end;
if (nums[end] < target) return end;
if (nums[start] < target) return start;
return -1;
}
};
解法2:将整个matrix视为一个一维array,因为下面两个条件决定了当m个行数组挨个连起来后的一维array仍然是单调递增(严格说是单调不递减)。所以用binary search即可。
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.
注意:这题与LintCode 38 Search a 2D Matrix II不一样,那题的条件是行对应元素递增,列对应元素递增,但若将m个行数组穿起来的一维数组则未必单调递增。也就是说本题的条件更严格。
但虽然本题解法不实用于LintCode 38,LintCode 38的解法倒适用于本题。因为本题更严格。见解法3。
代码如下:
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) {
int m = matrix.size();
if (m == 0) return false;
int n = matrix[0].size();
if (n == 0) return false;
int start = 0, end = m * n - 1;
while(start + 1 < end) {
int mid = start + (end - start) / 2;
int row = mid / n;
int col = mid % n;
if (matrix[row][col] < target) {
start = mid;
} else if (matrix[row][col] > target) {
end = mid;
} else {
return true;
}
}
if (matrix[start / n][start % n] == target) return true;
if (matrix[end / n][end % n] == target) return true;
return false;
}
};
解法3:即LintCode 38的解法。从右上角开始,每次行+1或列-1,直到找到target。代码如下:
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) {
int m = matrix.size();
if (m == 0) return false;
int n = matrix[0].size();
if (n == 0) return false;
int count = 0;
int row = 0;
int col = n - 1; //start from the right top point
while (row < m && col >= 0) {
if (matrix[row][col] > target) {
col--;
} else if (matrix[row][col] < target) {
row++;
} else {
return true;
}
}
return matrix[count / n][count % n] == target;
}
};
二刷,好像上面的 return matrix[count / n][count % n] == target; 不需要
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) {
int nRow = matrix.size();
if (nRow == 0) return false;
int nCol = matrix[0].size();
if (nCol == 0) return false;
int row = 0, col = nCol -1;
while (row < nRow && col >= 0) {
if (matrix[row][col] > target) {
col -= 1;
} else if (matrix[row][col] < target) {
row += 1;
} else {
return true;
}
}
return false;
}
};
本文探讨了在有序二维矩阵中高效查找特定值的三种方法。包括两次二分查找、将矩阵视为一维数组进行二分查找及从右上角开始逐行逐列逼近目标的策略。

被折叠的 条评论
为什么被折叠?



