您的位置:首页 > 其它

【LeetCode从零单刷】Search a 2D Matrix I & II

2015-10-30 11:10 519 查看
I 题目:

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
.
解答:
因为排序过,思路很清晰。建立每行首元素的索引,然后行二分搜索,最后列二分搜索。复杂度是O(lg(m) + lg(n))。但是难点在于细节:

这里的搜索可能 False,也就是找不到元素。因此,如果 first = 1,last = 2,mid = (first + last)/2 = 1。下一次如果 first = mid = 1,又陷入了循环;
因为除法取整的原因,有可能 last 一直无法取到。如果 first = 1,last = 2,mid = (first + last)/2 = 1。下一次如果 first = mid = 1,还是取不到 last = 2 的值。因此需要多判断一次 last 的值;
关于每行首元素的索引中的搜索,不同于列搜索。即使 target > 索引中的最大值,还是有可能存在此元素。例如 target = 30 > 23,依然存在
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
vector<int> rowfirst;
for(int i=0; i<matrix.size(); i++)  rowfirst.push_back(matrix[i][0]);

int head = 0;
int tail = matrix.size() - 1;
while(head <= tail){
if(head + 1 == tail || head == tail){
if(target == rowfirst[head] || target == rowfirst[tail])   return true;
else    break;
}
int mid = (head + tail) / 2;
if(target > rowfirst[tail])  head = tail;
else if(target == rowfirst[mid] || target == rowfirst[tail])  return true;
else if(target < rowfirst[mid])   tail = mid;
else if(target > rowfirst[mid])   head = mid;
}
if(head > tail) return false;

int first = 0;
int last  = matrix[0].size() - 1;
while(first <= last){
if(first == last || first + 1 == last){
if (matrix[head][first] == target || matrix[head][last] == target)   return true;
else    return false;
}
int mid = (first + last) / 2;
if(target == matrix[head][mid] || target == matrix[head][last])   return true;
else if(target < matrix[head][mid])   last = mid;
else if(target > matrix[head][mid])   first = mid;
}
return false;
}
};


当然,二分搜索还有一种实现方法,就是每次必然移动一位。例如:head = mid +1,tail = mid- 1

只是这样实现,需要在循环中单独预先判断 head,tail,mid 处的值。具体实现可参见:《Search in Rotated Sorted Array I & II》

II 题目:

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 in ascending from left to right.
Integers in each column are sorted in ascending from top to bottom.
For example,

Consider the following matrix:

[
[1,   4,  7, 11, 15],
[2,   5,  8, 12, 19],
[3,   6,  9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]

Given target =
5
, return
true
.

Given target =
20
, return
false
.

解答:

我的做法比较简单,对每行的首尾遍历范围,行内二分搜索。算法复杂度为 O(m * log n):

class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
if (matrix.empty() || matrix[0].empty()) return false;

int m = matrix.size();
int n = matrix[0].size();

int left, right, mid;
for (int i = 0; i<m; i++) {
if (matrix[i][0] <= target && target <= matrix[i][n - 1]) {
left = 0;
right = n - 1;
while(left <= right) {
mid = (left + right) / 2;
if (matrix[i][left] == target || matrix[i][right] == target || matrix[i][mid] == target)
return true;

if (matrix[i][mid] > target) right = mid - 1;
if (matrix[i][mid] < target) left = mid + 1;
}
}
}
return false;
}
};但其实还有一种 O(n ^ 1.58) 的复杂度:分治法。
以矩形中点为基准,将矩阵拆分成左上,左下,右上,右下四个区域。若中点值 < 目标值,则舍弃左上区域,从其余三个区域再行查找若中点值 > 目标值,则舍弃右下区域,从其余三个区域再行查找。

具体算法实现与复杂度推导(利用 “主定理 master theorem” 计算复杂度)见:传送门
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: