跳到主要内容

240. 搜索二维矩阵 II [medium]

240. 搜索二维矩阵 II [medium]

https://leetcode-cn.com/problems/search-a-2d-matrix-ii/

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该矩阵具有以下特性:

每行的元素从左到右升序排列。 每列的元素从上到下升序排列。 示例:

现有矩阵 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]
]

给定 target = 5,返回 true。

给定 target = 20,返回 false。

通过次数66,298 | 提交次数160,644

Second Try

2020-07-16

没想到还可以把这个矩阵当作一个二叉搜索树来处理:对于左下角的元素node, 比node大的都在右边,比node小的都在上边,模拟二叉搜索树的搜索过程就搞定了。

算是一个让人耳目一新的解法,对数据结构的理解真是透彻,不过一般也很难出现这么符合要求的矩阵。

class Solution(object):
def searchMatrix(self, matrix, target):
"""
:type matrix: List[List[int]]
:type target: int
:rtype: bool
"""
if not (len(matrix) and len(matrix[0])):
return False

m, n = len(matrix), len(matrix[0])
i, j = m - 1, 0
while 0 <= i < m and 0<= j < n:
if target < matrix[i][j]:
i -= 1
elif target > matrix[i][j]:
j += 1
else:
return True
return False
  • 执行用时:80 ms, 在所有 Python 提交中击败了33.33%的用户
  • 内存消耗:16.8 MB, 在所有 Python 提交中击败了33.33%的用户

First Try

2020-07-16

用了二分法left bound来处理,找到idx,使得arr[idx] <= target, ,arr[idx + 1] > tarrget。但是感觉还是不够高效,根本不用二分法,在按行列遍历的时候就可以通过大小进行判断了。

重新练手了一波left bound,才几天没写就没法一波写出来,一是对于最后返回left还是right迟滞, 二是在arr[mid] == target的时候,是该处理left = mid - 1还是right = mid - 1也存在迟疑。 但不管如何,left bound和right bound都是这么个处理流程,在每一轮中总归是要left = mid + 1或者right = mid - 1. 下面left bound的写法可以认为right一直都是压着>= mid的边缘,因此最后只要选择right就有arr[right] <= target

不过还是觉得对二分法的理解没有前几天那么自然了。。。

class Solution(object):
def searchMatrix(self, matrix, target):
"""
:type matrix: List[List[int]]
:type target: int
:rtype: bool
"""
# 还是用二分法来处理

def left_bound(arr, target):
"""return idx, arr[idx] <= target, arr[idx + 1] > target"""
left, right = 0, len(arr) - 1
while left <= right: # 最后的状态就是left = right + 1, 较小值反而是right
mid = (left + right) // 2
if arr[mid] < target:
left = mid + 1
elif arr[mid] > target:
right = mid - 1
elif arr[mid] == target:
left = mid + 1
return right

def bisearch(arr, target):
left, right = 0, len(arr) - 1
while left <= right:
mid = (left + right) // 2
if arr[mid] < target:
left = mid + 1
elif arr[mid] > target:
right = mid - 1
elif arr[mid] == target:
return True
return False

# 测试集又来了两个坑, []和[[]]两个矩阵
if not (len(matrix) and len(matrix[0])):
return False

row = [row[0] for row in matrix]
row_idx = left_bound(row, target)
column_idx = left_bound(matrix[0], target)

# 仅仅至少缩小到左边矩形的大小,感觉还是不够高效
for i in range(row_idx + 1):
for j in range(column_idx + 1):
if matrix[i][j] == target:
return True
return False
  • 执行用时:448 ms, 在所有 Python 提交中击败了7.94%的用户
  • 内存消耗:16.6 MB, 在所有 Python 提交中击败了33.33%的用户
  • improved verseion

对筛选后的区域,每一行依然使用二分法,能再快一些。

class Solution(object):
def searchMatrix(self, matrix, target):
"""
:type matrix: List[List[int]]
:type target: int
:rtype: bool
"""
# 还是用二分法来处理

def left_bound(arr, target):
"""return idx, arr[idx] <= target, arr[idx + 1] > target"""
left, right = 0, len(arr) - 1
while left <= right: # 最后的状态就是left = right + 1, 较小值反而是right
mid = (left + right) // 2
if arr[mid] < target:
left = mid + 1
elif arr[mid] > target:
right = mid - 1
elif arr[mid] == target:
left = mid + 1
return right

def bisearch(arr, target):
left, right = 0, len(arr) - 1
while left <= right:
mid = (left + right) // 2
if arr[mid] < target:
left = mid + 1
elif arr[mid] > target:
right = mid - 1
elif arr[mid] == target:
return True
return False

# 测试集又来了两个坑, []和[[]]两个矩阵
if not (len(matrix) and len(matrix[0])):
return False

row = [row[0] for row in matrix]
row_idx = left_bound(row, target)
column_idx = left_bound(matrix[0], target)

# 仅仅至少缩小到左边矩形的大小,感觉还是不够高效
for i in range(row_idx + 1):
if bisearch(matrix[i][:column_idx + 1], target):
return True
return False
  • 执行用时:144 ms, 在所有 Python 提交中击败了17.76%的用户
  • 内存消耗:16.6 MB, 在所有 Python 提交中击败了33.33%的用户