您的位置:首页 > 编程语言 > C语言/C++

Leetcode 074 探索二维矩阵 Python C++ 史上最详细题解系列

2018-08-11 10:07 555 查看


每天更新一道python or C++ leetcode题,力求讲解清晰准确,客官们可以点赞或者关注。

 

题目:

编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:

  • 每行中的整数从左到右按升序排列。
  • 每行的第一个整数大于前一行的最后一个整数。

示例 1:

[code]输入:
matrix = [
[1,   3,  5,  7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
target = 3
输出: true

示例 2:

[code]输入:
matrix = [
[1,   3,  5,  7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
target = 13
输出: false

 

这道题明摆着让我们使用二分思路嘛。

但是在细节的处理上也有较多不同。

方法一:

 

这道题要求搜索一个二维矩阵,由于给的矩阵是有序的,所以很自然的想到要用二分查找法,我们可以在第一列上先用一次二分查找法找到目标值所在的行的位置,然后在该行上再用一次二分查找法来找是否存在目标值,代码如下:

C++:

[code]class Solution {
public:
bool searchMatrix(vector<vector<int> > &matrix, int target) {
if (matrix.empty() || matrix[0].empty()) return false;
if (target < matrix[0][0] || target > matrix.back().back()) return false;
int left = 0, right = matrix.size() - 1;
//先找目标数在哪一行
while (left <= right) {
int mid = (left + right) / 2;
if (matrix[mid][0] == target) return true;
else if (matrix[mid][0] < target) left = mid + 1;
else right = mid - 1;
}
//行数为right的值
int tmp = right;
left = 0;
right = matrix[tmp].size() - 1;
//接下来就是在一行里实现二分查找了
while (left <= right) {
int mid = (left + right) / 2;
if (matrix[tmp][mid] == target) return true;
else if (matrix[tmp][mid] < target) left = mid + 1;
else right = mid - 1;
}
return false;
}
};

方法二:

利用matrix的特性(每一行的数字的数目相同),可以直接定位到所有数据的中间的数。实际上这就是把二维数组变成一个一维数组,这其中的坐标转换是逻辑关键点。

Python:

[code]class Solution:
def searchMatrix(self, matrix, target):
"""
:type matrix: List[List[int]]
:type target: int
:rtype: bool
"""
m = len(matrix)
if m == 0:
return False
n = len(matrix[0])
if n == 0:
return False
#l-r是矩阵包含的所有数字
l, r = 0, m * n - 1
while l <= r:
#最中间的数字
mid = (l + r) // 2
#mid//n为最中间数字所在的行,mid%n为所在的列
if matrix[mid // n][mid % n] == target:
return True
elif matrix[mid // n][mid % n] < target:
l = mid + 1
else:
r = mid - 1
return False

 

C++

[code]// One binary search
class Solution {
public:
bool searchMatrix(vector<vector<int> > &matrix, int target) {
if (matrix.empty() || matrix[0].empty()) return false;
if (target < matrix[0][0] || target > matrix.back().back()) return false;
int m = matrix.size(), n = matrix[0].size();
int left = 0, right = m * n - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (matrix[mid / n][mid % n] == target) return true;
else if (matrix[mid / n][mid % n] < target) left = mid + 1;
else right = mid - 1;
}
return false;
}
};

总结:方法一中,tmp = right,是因为left不能确定正确的行数,因为left+1是因为matrix[mid][0] < target,但是target还是有可能在这一行的,所以只有right的值才代表target所在的行数。

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: