本文共 1984 字,大约阅读时间需要 6 分钟。
利用矩阵 “从上到下递增、从左到右递增”
的特点,建模为 二叉搜索树的查找 问题
利用矩阵 “从上到下递增、从左到右递增”
的特点,将矩阵逆时针旋转 45° ,并将其转化为图形式,发现其类似于 ,即对于每个元素,其左分支元素更小、右分支元素更大。
“根节点” 对应的是矩阵的 “左下角” 和 “右上角” 元素,本文称之为 标志数 ,
①. 以 matrix 中的 左下角元素 为标志数 flag ,则有:若 flag > target ,则 target 一定在 flag 所在 行的上方 ,即 flag 所在行可被消去。
若 flag < target ,则 target 一定在 flag 所在 列的右方 ,即 flag 所在列可被消去。
②. 以 matrix 中的 右下角元素 为标志数 flag ,则有:
若 flag > target ,则 target 一定在 flag 所在 列的左方 ,即 flag 所在行可被消去。
若 flag < target ,则 target 一定在 flag 所在 行的下方 ,即 flag 所在列可被消去。
选①的算法流程:
从矩阵 matrix 左下角元素(索引设为 (i, j) )开始遍历,并与目标值对比:
i) 当 matrix[i][j] > target 时,执行 i-- ,即消去第 i 行元素;ii) 当 matrix[i][j] < target 时,执行 j++ ,即消去第 j 列元素;iii) 当 matrix[i][j] = target 时,返回 truetrue ,代表找到目标值。
若行索引或列索引越界,则代表矩阵中无目标值,返回 false。
每轮 i 或 j 移动后,相当于生成了“消去一行(列)的新矩阵”, 索引(i,j) 指向新矩阵的左下角元素(标志数),因此可重复使用以上性质消去行(列)。
效果看图
【代码】
class Solution: def findNumberIn2DArray(self,matrix,target): i, j = len(matrix) - 1, 0 # 左下角 while i >= 0 and j < len(matrix[0]): if matrix[i][j] > target: i -= 1 elif matrix[i][j] < target: j += 1 else: # 找到为真 return True return False'''作者:Krahets链接:https://leetcode-cn.com/leetbook/read/illustration-of-algorithm/5vl81e/来源:力扣(LeetCode)著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。'''
【复杂度分析】
【补充知识点】
len(矩阵) 返回的是 二维矩阵 的第一维长度
什么是二叉搜索树?
【扩展】
若以 右下角元素 为标志数 flag 如果大的话,先收缩行;小的话,收缩列class Solution: def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool: i, j = 0,len(matrix[0])-1 # 右上角 while i < len(matrix) and j >=0: if matrix[i][j] > target: j -= 1 elif matrix[i][j] < target: i += 1 else: return True return False
但右上角元素的坐标不好判断
发现先取 len(matrix[0]) 的值,才行。但是运行时间太慢了~if not matrix: return False m, n = len(matrix), len(matrix[0])