leetcode_240 搜索二维矩阵 II
1. 题意
编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:
每行的元素从左到右升序排列。
每列的元素从上到下升序排列。
2. 题解
这个题目和搜索二维矩阵相似。
唯一不同是,
这个题目不保证前一行的末尾元素小于当前行的开头元素了。
因此不能压成一个一维数组进行处理了。
2.1 逐行、列二分
直接逐行、列二分。
逐列二分,时间复杂度 O(nlogm) O(n \\log m) O(nlogm)
class Solution {public: bool searchMatrix(vector<vector<int>>& matrix, int target) { if (matrix.empty()) return false; int R = matrix.size(); int C = matrix[0].size(); for (int i = 0; i < C; ++i) { int l = 0; int r = R - 1; while ( l <= r ) { int mid = ((r - l) >> 1) + l; int v = matrix[mid][i]; if ( v == target ) return true; if ( v < target ) l = mid + 1; else r = mid - 1; } } return false; }};
逐行二分,时间复杂度 O(mlogn) O(m \\log n) O(mlogn)
class Solution {public: bool searchMatrix(vector<vector<int>>& matrix, int target) { if (matrix.empty()) return false; int R = matrix.size(); int C = matrix[0].size(); for (int i = 0; i < R; ++i) { int l = 0; int r = C; while ( l < r ) { int mid = ((r - l) >> 1) + l; int v = matrix[i][mid]; if ( v == target ) return true; if ( v > target ) r = mid; else l = mid + 1; } } return false; }};
其实我们还可以小小的优化下:
对于最大元素(最右边)小于target
的行,我们可以直接舍弃掉。
同样对于最小元素(最左边)大于target
的行,我们可以直接舍弃掉。
由于任一列都是有序的,
因此可以二分查找第一个末尾元素不大于target
的行ub
;
同样可以二分查找第一个首元素大于target
的行bb
。
再在[ub,bb)
所在范围的这些行进行行二分。
class Solution {public: bool searchMatrix(vector<vector<int>>& matrix, int target) { if (matrix.empty()) return false; int n = matrix.size(); int R = n; int C = matrix[0].size(); int l; int r; l = 0; r = R; while ( l < r) { int mid = ((r - l) >> 1) + l; int v = matrix[mid][C - 1]; if ( v == target) return true; if ( v > target) r = mid; else l = mid + 1; } int ub = r; l = ub; r = R; while ( l < r) { int mid = ((r - l) >> 1) + l; int v = matrix[mid][0]; if ( v == target) return true; if ( v > target) r = mid; else l = mid + 1; } int bb = r; for (int i = ub;i < bb; ++i) { auto it = lower_bound(matrix[i].begin(), matrix[i].end(), target); if (it != matrix[i].end() && *it == target) return true; } return false; }};
2.2 二叉搜索树
同搜索二维矩阵一样,可以将矩阵看成以右上角为根的二叉搜索树。
图也用上个题目的图吧。
时间复杂度 O(n+m) O(n+m) O(n+m)
class Solution {public: bool searchMatrix(vector<vector<int>>& matrix, int target) { if (matrix.empty()) return false; int n = matrix.size(); int R = n; int C = matrix[0].size(); int x = 0; int y = C - 1; while ( x < R && y >= 0) { int v = matrix[x][y]; if ( v == target) return true; if ( v > target) --y; else ++x; } return false; }};
参考
三叶