74. 搜索二维矩阵 [medium]
74. 搜索二维矩阵 [medium]
https://leetcode-cn.com/problems/search-a-2d-matrix/
编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:
每行中的整数从左到右按升序排列。 每行的第一个整数大于前一行的最后一个整数。 示例 1:
输入:
matrix = [
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
target = 3
输出: true
示例 2:
输入:
matrix = [
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
target = 13
输出: false
通过次数49,222 | 提交次数128,665
Second Try
2020-07-03
虚拟展开成一维数组,idx标号可以方便转化为m,n矩阵坐标。
看题解才想起还可以这么搞,之前在数独的题目中已经用过类似的了。
class Solution(object):
def searchMatrix(self, matrix, target):
"""
:type matrix: List[List[int]]
:type target: int
:rtype: bool
"""
# 虚拟展开成一维数组,idx标号可以方便转化为m,n矩阵坐标
if len(matrix) == 0 or len(matrix[0]) == 0:
return False
m, n = len(matrix), len(matrix[0])
# 行坐标是[0, m-1], 列坐标范围是[0, n-1]
midx = lambda idx: divmod(idx, n)
# 二分法开始
left, right = 0, m * n - 1
while left <= right:
mid = left + (right - left) // 2
r, c = midx(mid)
if matrix[r][c] == target:
return True
elif matrix[r][c] > target:
right = mid - 1
elif matrix[r][c] < target:
left = mid + 1
return False
- 执行用时:16 ms, 在所有 Python 提交中击败了95.68%的用户
- 内存消耗:13.6 MB, 在所有 Python 提交中击败了60.00%的用户
First Try
2020-07-03
通过左边界确定了行,然后再通过普通二分法确定列,是一个比较绕的写法,但复杂度跟上面的是一样的。lg(m) + lg(n) = lg(mn)
class Solution(object):
def searchMatrix(self, matrix, target):
"""
:type matrix: List[List[int]]
:type target: int
:rtype: bool
"""
# 展平也算是O(N)了,所以还是得从最开始就用二分法LgN才行
# 如果在某一行中,则改行第一个元素是left bound,第二行是right bound
# todo:考虑matrix为空的情况
if len(matrix) == 0 or len(matrix[0]) == 0:
return False
# 先确定一波在哪一行,这一行的起点必须小于target,但是下一行的起点必须大于target
# 因此应该是在跳出循环后的right边界
left, right = 0, len(matrix) - 1
while left <= right:
mid = (left + right) / 2
if matrix[mid][0] < target:
left = mid + 1
elif matrix[mid][0] > target:
right = mid - 1
elif matrix[mid][0] == target:
return True
# print("phase one", left, right)
# 不需要关心left,又贡献了一个bug...
# if left >= len(matrix) or right < 0:
if right < 0:
return False
row = right
# 考虑在某一行里的所有元素,用普通的二分法就行了
left, right = 0, len(matrix[0]) - 1 # 靠,差点又写成了right = len(matrx[0])
# print("next phase", left, right, row)
while left <= right:
mid = (left + right) / 2
if matrix[row][mid] < target:
left = mid + 1
elif matrix[row][mid] > target:
right = mid - 1
elif matrix[row][mid] == target:
return True
# print("end", left, right)
return False
- 执行用时:20 ms, 在所有 Python 提交中击败了82.52%的用户
- 内存消耗:13.4 MB, 在所有 Python 提交中击败了100.00%的用户