开头语:
这篇总结建议和专栏–力扣刷题(十六)还有–剑指刷题(一)一起阅读,总结。因为力扣刷题(十六)是力扣刷题(十五)的进阶版。十五的条件更苛刻且特殊,因为它规定了每行的第一个整数大于前一行的最后一个整数。而十六并没有规定两行之间彼此的关系。
题目描述:
编写一个高效的算法来判断 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
思路:
这里我们直接用最一般的思路去求解这道题目。题目中需要判断是否存在一个目标值,常见的方法是想到二分法,从矩阵的最中间位置取值和target比较,决定接下来运动的方向。但是”矩阵“、”字符串“、”数组“这种问题其实有一个共性思路就是从最后一个位置出发(比如数组,大多数人都是从左往右查找。但其实可以逆向思维从最后往前做往往事半功倍。)。这道题就是如此,我们可以:
- 从右上角开始取值(记为A)与target比较(自然而然也可以从左下角开始取值与target比较),如果 A > target,那么我们就可以不用判断同列A下面的数了,因为同列只会越来越大,而这里的A已经是同列里最小的了,所以不用往下走了。因此我们要做的操作就是”删除整列";
- 如果 A < target,那么我们就可以不用判断同行A旁边的数了。因为同行是递增的关系,如果最右的A都比target小,那么A左边的数也一定都比target小。因此没有比较的必要,我们要做的操作就是”删除整行";
- 依次类推,直至找到符合条件的A,并输出true。如果没有找到,则输出false
测试用例注意:
- 空矩阵
- 行向量、列向量;(这个坑主要是如果行索引i由列的最大长度控制,那么就会超出索引长度;因此必须行索引由行的最大长度控制;列索引由列的最大长度控制)
- 思想上用的是”删除“,但是如果你用 del 或者pop删除的话会有问题就是索引比较麻烦,因此要变通!真正实现的时候我们是通过让行索引加一或者列索引减一去做,这样其实就间接达到了”删除“的目的,还不会导致索引混乱!!
通用code:
class Solution(object):
def searchMatrix(self, matrix, target):
"""
:type matrix: List[List[int]]
:type target: int
:rtype: bool
"""
i = 0
if matrix:
j = len(matrix[0]) - 1
else:
return False
while j >= 0 and i <= len(matrix)-1:
if matrix[i][j] > target:
j -= 1
elif matrix[i][j] < target:
i += 1
else:
return True
return False