【剑指offer】04-二维数组中的查找
题目:
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
思考:
1、遍历,用i, j分别遍历每行每列,找到相同的数据就返回True,没找到就返回False
class Solution: # array 二维列表 def FindI(self, target, array): """一行一行的遍历""" m, n = len(array), len(array[0]) # m有多少行 n有多少列 for i in range(0, m): for j in range(0, n): if array[i][j] == target: return True return False # 循环中所有都执行完了之后还没找到,才return False
写的过程中遇到的问题:
一开始吧return False写在了循环里面,作为if else的条件。但是这样的话,第一遍没找到数就会return False了。所以要把这句写在循环外面,二维数组中所有的都遍历完了之后,还没有找到该数,才返回False
该方案的缺点:
每一个数都遍历,效率低
于是参考书籍,拥有方案2:
2、从右上角开始遍历,如果右上角的数值比target大 -> 该列都比target大,可以不用再继续比较该列的数值。
如果右上角的数值比target小 -> 该行都比target小,可以不用再继续比较该行的数值。具体例子见图
def FindII(self, target, array): """从右上角的元素开始找""" m, n = len(array), len(array[0]) row, col = 0, n-1 while row < m and col >= 0: if target < array[row][col]: col -= 1 elif target > array[row][col]: row += 1 else: return True return False
写的过程中遇到的问题:
row一开始从1开始。遍历都是从0开始的。
col一开始取值为n。跟上面一样,n是长度,但是遍历的时候,最后一个数的下标是n-1
while循环条件不会。当行遍历到最后一行 且 列遍历到第一列(是从后往前遍历列)的时候,即到达了数组中左下角的那个数,都还没找到target,就退出循环。col可以取0。
该方法降低了时间复杂度,效率高。
为什么不从左上和右下开始遍历呢?
-> 这有啥意义?左上开始,下边的和右边的都不能排除,还是得一行一行遍历。只有从右上或者左下开始,才有机会排除掉某行或某列的值。
其实还得关注一下每道题的测试用例【顺带训练测试思维呗】,这道题用例:
二维数组每个边角的值:左上、左下、右上、右下。eg. 1、9、6、15
中间的值:eg. 4、7
不存在的值:eg. 100、99、空值