[Leetcode] 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.
For example,
Consider the following matrix:
[ [1, 3, 5, 7], [10, 11, 16, 20], [23, 30, 34, 50] ]
Given target = 3
, return true
.
从右上角向左下角搜索,初始row = 0, col = n - 1; 如果当前值等于目标值,返回真,如果以目标值大,则舍弃当前列,否则舍弃当前行。
1 class Solution { 2 public: 3 bool searchMatrix(vector<vector<int> > &matrix, int target) { 4 int row = 0, col = matrix[0].size() - 1; 5 while (row < matrix.size() && col >=0) { 6 if (matrix[row][col] == target) { 7 return true; 8 } else if (matrix[row][col] > target) { 9 --col; 10 } else { 11 ++row; 12 } 13 } 14 return false; 15 } 16 };
第二遍做的时候发现其实这个矩阵不完全是杨氏矩阵,可以使用二分搜索,下面是代码。
1 class Solution { 2 public: 3 bool searchMatrix(vector<vector<int> > &matrix, int target) { 4 int m = matrix.size(); 5 int n = matrix[0].size(); 6 int L = 0, R = n * m - 1, M; 7 int col, row; 8 while (L <= R) { 9 M = L + ((R - L) >> 1); 10 row = M / n; 11 col = M % n; 12 if (matrix[row][col] > target) R = M - 1; 13 else if (matrix[row][col] < target) L = M + 1; 14 else return true; 15 } 16 return false; 17 } 18 };
上面是对所有元素二分,复杂度是log(n*m),还可以更优化一点,对于普通的杨氏矩阵也适用,复杂度为log(n)+log(m).
1 class Solution { 2 public: 3 bool searchMatrix(vector<vector<int> > &matrix, int target) { 4 int row = lowerBound(matrix, target); 5 if (row == -1) return false; 6 return binSearch(matrix, target, row); 7 } 8 9 int lowerBound(vector<vector<int> > &matrix, int target) { 10 int L = 0, R = matrix.size() - 1, M; 11 while (L <= R) { 12 M = L + ((R - L) >> 1); 13 if (matrix[M][0] <= target) L = M + 1; 14 else R = M - 1; 15 } 16 return R; 17 } 18 19 bool binSearch(vector<vector<int> > &matrix, int target, int row) { 20 int L = 0, R = matrix[row].size() - 1, M; 21 while (L <= R) { 22 M = L + ((R - L) >> 1); 23 if (matrix[row][M] < target) L = M + 1; 24 else if (matrix[row][M] > target) R = M - 1; 25 else return true; 26 } 27 return false; 28 } 29 };