在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
示例:
现有矩阵 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。
解题思路:
因为每行每列都按照从大到小顺序排列,所以可以有如下思路:
对第i行,这一行最大的数必然是i[-1],最小的数必然是i[0],因此从第一行开始对每行进行遍历:
- 如果target>该行最大数,则target必然在下一行或不存在,故直接遍历下一行即可,即pass;
- 如果target<该行最小数,则target必然在之前的行,又因为是从第一行开始遍历的,所以必然不存在,返回False;
- 如果target不属于上面两种情况,那么target可能在这一行,也可能在下一行,也可能不存在。下面对这一行按列遍历:
- 如果target等于当前行当前列的数,则返回True;
- 如果target大于当前行当前列的数,那么应该继续遍历下一个数,即pass;
- 如果target小于当前行当前列的数,那么target要么不存在要么就在下一行,因此应该break;
当所有行遍历完成后,如果还没找到target,则说明不存在,返回False。
class Solution:
def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
# matrix[1][1]; matrix[-1][-1]
if len(matrix):
if len(matrix[0]):
m_min = matrix[0][0]
m_max = matrix[-1][-1]
if target < m_min or target > m_max:
return False
else:
rows = len(matrix)
cols = len(matrix[0])
for index in range(rows):
r_max = matrix[index][-1]
r_min = matrix[index][0]
if target > r_max: # 大于该行最大数,则必在后面的行
pass
elif target < r_min: # 小于最小数,则必不存在
return False
else: # 否则target要么在这一行,要么在下一行
for c_index in range(cols):
if matrix[index][c_index] == target: # 就是这个
return True
elif matrix[index][c_index] < target: # 继续下一个
pass
else: # 大于情况一旦出现说明不在这一行
break
return False # 遍历完成后还没找到则不存在
else:
return False
else:
return False
问题总结:
1. 逻辑比较复杂,需要想清楚;
2. 对List[List[int]]的操作不太熟,还要坚持做题;
3. 对特殊情况的排除,即matrix=[]和matrix=[[]];
做题过程中出现过的错误及最后结果:
执行结果:通过
执行用时:56 ms, 在所有 Python3 提交中击败了32.04%的用户
内存消耗:17.8 MB, 在所有 Python3 提交中击败了100.00%的用户
看到的另一种巧妙的解法:(链接:https://leetcode-cn.com/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/solution/gao-su-jie-fa-qing-xi-tu-jie-by-ml-zimingmeng/)
从左下角开始遍历,当该值小于 target 值时,向右搜索;大于 target 值时,向上搜索。如果找到 target 则返回 True,否则返回 False。
妙啊!