一, 题目描述
编写一个高效的算法来搜索 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.
链接:
二, 题解
方法一: 暴力搜索法
方法一最容易想到, 直接使用两个 for 循环遍历矩阵, 当遇到与 target 相等的值时直接返回 True 即可. 此法显然不是出题人想要的结果.
完成时间: 2020.05.07
- class Solution:
- def searchMatrix(self, matrix, target):
- """
- :type matrix: List[List[int]]
- :type target: int
- :rtype: bool
- """
- for i in range(len(matrix)):
- for j in range(len(matrix[0])):
- if matrix[i][j] == target:
- return True
- return False
方法一使用了两趟循环:
时间复杂度:\(O(m * n)\) ,\(m\) 指的是矩阵行数,\(n\) 指的是矩阵列数.
空间复杂度:\(O(1)\).
方法二: 二分查找
方法二是对方法一的优化. 由于矩阵的行和列都已经排好序, 那么可以利用二分查找加快目标值的查找速度. 具体做法是当按行遍历矩阵时, 使用二分查找法对每行进行查找.
注意:
二分查找算法里面有很多细节需要注意, 不然极容易出错.
完成时间: 2020.05.09
- class Solution:
- def searchMatrix(self, matrix, target):
- """
- :type matrix: List[List[int]]
- :type target: int
- :rtype: bool
- """
- # 矩阵为空, 直接返回 False
- if not matrix:
- return False
- rows = len(matrix)
- columns = len(matrix[0])
- for i in range(rows):
- left = 0
- right = columns - 1 # 注意
- while left <= right: # 注意要带等号, 不然当数组只有一个值时, 可能会漏掉结果
- mid = (left + right) // 2
- if matrix[i][mid]> target:
- right = mid - 1
- elif matrix[i][mid] == target:
- return True
- elif matrix[i][mid] <target:
- left = mid + 1
- return False
方法二使用了两趟循环:
时间复杂度: for 循环的时间复杂度为 \(O(m)\) ,\(m\) 指的是矩阵行数, while 循环的时间复杂度为 \(O(\log_{2}n)\),n 为矩阵的列数, 所以总的时间复杂度为 \(O(m*\log_{2}n)\);
空间复杂度:\(O(1)\).
方法三: 利用本题矩阵的特点
既然题目告诉我们矩阵每行的元素从左到右升序排列, 每列的元素从上到下升序排列, 那么我们可以利用这一特性来巧妙解题.
首先设置变量 row 表示行标, col 表示列标, 将 row 的初始值设为 0, 表示第一行, 将 col 的初始值设为矩阵最后一列的下标;
然后使用一个 while 循环遍历矩阵, 若 matrix[row][col]> target 成立时, 说明当前值比目标值 target 大, 列标 col 需要左移来找到更小的值与 target 相比较; 若 matrix[row][col] <target 成立时, 说明当前值比目标值 target 小, 行标 row 需要下移来找到更大的值与 target 相比较; 若 matrix[row][col] == target 成立时, 说明找到了目标值 target, 直接返回 True 即可;
最后, 若遍历结束仍然没有找到目标值 target, 说明矩阵中不存在目标值 taregt, 返回 False 即可.
注意:
与目标值比较的初始值选取的位置必须在矩阵的左下角和右上角处
完成时间: 2020.05.07
- class Solution:
- def searchMatrix(self, matrix, target):
- """
- :type matrix: List[List[int]]
- :type target: int
- :rtype: bool
- """
- if not matrix:
- return False
- row, col = 0, len(matrix[0]) - 1
- while row < len(matrix) and col>= 0:
- if matrix[row][col]> target:
- col -= 1
- elif matrix[row][col] < target:
- row += 1
- else:
- return True
- return False
方法三使用了一趟循环:
时间复杂度:\(O(m + n)\) ,\(m\) 指的是矩阵行数,\(n\) 指的是矩阵列数. row 的最大值不超过矩阵行数 m,col 的最大值不超过矩阵列数 n.
空间复杂度:\(O(1)\).
来源: https://www.cnblogs.com/victorxiao/p/12860556.html