题目链接:https://leetcode.cn/problems/search-a-2d-matrix/
方法一:遍历
该方法就是遍历查找每个位置,看 target 是否出现。这个方法也能通过本题。
class Solution(object):
def searchMatrix(self, matrix, target):
# return any(target in row for row in matrix)
M, N = len(matrix), len(matrix[0])
for i in range(M):
for j in range(N):
if matrix[i][j] == target:
return True
return False
方法二:从左下角或者右上角开始查找
这个方法是利用了矩阵的性质,如果我们从右上角开始遍历:
class Solution(object):
def searchMatrix(self, matrix, target):
if not matrix or not matrix[0]:
return False
rows = len(matrix)
cols = len(matrix[0])
row, col = 0, cols - 1
while True:
if row < rows and col >= 0:
if matrix[row][col] == target:
return True
elif matrix[row][col] < target:
row += 1
else:
col -= 1
else:
return False
方法三:先寻找到所在行
该方法利用了题目给出的矩阵的性质:每行元素都是单调递增的,并且下一行的元素会比本行更大。所以:
如果 target 大于这一行的末尾元素,那么 target 一定不在这一行中,只能出现在矩阵的下面的行中。
那么,假如 t a r g e t < m a t r i x [ i ] [ N − 1 ] target < matrix[i][N - 1] target<matrix[i][N−1] 时,说明 target 可能在本行中出现,而且由于下面各行的元素都大于 m a t r i x [ i ] [ N − 1 ] matrix[i][N - 1] matrix[i][N−1],所以,不可能在下面的行中出现。此时,可以在本行中使用顺序查找,或者二分查找。
class Solution(object):
def searchMatrix(self, matrix, target):
M, N = len(matrix), len(matrix[0])
for i in range(M):
if target > matrix[i][N - 1]:
continue
if target in matrix[i]:
return True
return False
方法四:两次二分查找
这个方法可以说是方法三的改进。在方法三种,我们是先遍历找到 target 在哪一行,然后在该行遍历或者二分查找的 target 。其实也可以先用二分找到 target 所在的行,然后在该行二分找到 target。
具体做法是,先找到 m a t r i x [ i ] [ 0 ] matrix[i][0] matrix[i][0] 小于 target 并且 m a t r i x [ i + 1 ] [ 0 ] > t a r g e t matrix[i + 1][0] > target matrix[i+1][0]>target 的第 i i i 行,然后在该行内进行二分找到 target。
class Solution(object):
def searchMatrix(self, matrix, target):
M, N = len(matrix), len(matrix[0])
col0 = [row[0] for row in matrix]
target_row = bisect.bisect_right(col0, target) - 1
if target_row < 0:
return False
target_col = bisect.bisect_left(matrix[target_row], target)
if target_col >= N:
return False
if matrix[target_row][target_col] == target:
return True
return False
方法五:全局二分
这个方法,是我们在二维矩阵上进行二分查找,这其实相当于把二维矩阵当做一维来做,要求每一行的最后一个元素小于下一行的第一个元素。
根据 mid 求出在二维矩阵中的具体位置,然后判断 left 和 right 的移动方式。整体做法和一维数组的二分没有区别。
class Solution(object):
def searchMatrix(self, matrix, target):
M, N = len(matrix), len(matrix[0])
left, right = 0, M * N - 1
while left <= right:
mid = left + (right - left) // 2
cur = matrix[mid // N][mid % N]
if cur == target:
return True
elif cur < target:
left = mid + 1
else:
right = mid - 1
return False
方法六:reshape成一维数组
如果用python刷题,在leetcode中是支持使用 numpy 的,可以把 matrix 成一维有序的数组,然后按照一维数组去操作查找。
import numpy as np
class Solution(object):
def searchMatrix(self, matrix, target):
matrix = np.reshape(matrix, [1, -1])
return target in matrix
题目链接:https://leetcode.cn/problems/search-a-2d-matrix-ii/
方法一:直接查找
直接遍历整个矩阵 matrix \textit{matrix} matrix,判断 target \textit{target} target 是否出现即可。
class Solution:
def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
for row in matrix:
for element in row:
if element == target:
return True
return False
方法二:减而治之
(1) 选择左下角为起点,以下展示了「减治」的过程
总结出搜索的规律是:
class Solution:
def searchMatrix(self, matrix, target):
rows, cols = len(matrix), len(matrix[0])
# 起点:左下角
x, y = rows-1, 0
# 不越界的条件是:行大于等于 0,列小于 cols
while x >= 0 and y < cols:
if matrix[x][y] > target:
x -= 1
elif matrix[x][y] < target:
y += 1
else:
return True
return False
复杂度分析:
(2) 如果选择右上角为起点,以下展示了「减治」的过程
总结出「搜索」的规律是:
class Solution:
def searchMatrix(self, matrix, target):
# 特判
rows, cols = len(matrix), len(matrix[0])
# 起点:右上
x, y = 0, cols-1
# 不越界的条件是:行小于 rows,列大于等于 0
while x < rows and y >= 0:
if matrix[x][y] > target:
y -= 1
elif matrix[x][y] < target:
x += 1
else:
return True
return False
方法三:二分查找
由于矩阵 matrix \textit{matrix} matrix 中每一行的元素都是升序排列的,因此我们可以对每一行都使用一次二分查找,判断 target \textit{target} target 是否在该行中,从而判断 target \textit{target} target 是否出现。
(1) 详细版
class Solution:
def searchMatrix(self, matrix, target):
def binay_search(nums, target):
l, r = 0, len(nums) - 1
while l <= r:
mid = (l + r) // 2
if nums[mid] == target:
return True
if nums[mid] < target:
l = mid + 1
if nums[mid] > target:
r = mid - 1
return False
cols = len(matrix[0])
for line in matrix:
if line[0] <= target and line[cols - 1] >= target:
if binay_search(line, target):
return True
return False
(2) 简化版
class Solution:
def searchMatrix(self, matrix, target):
for row in matrix:
ind = bisect.bisect_left(row, target)
if ind < len(matrix[0]) and row[ind] == target:
return True
return False