74 搜索整体有序的二维数组 点击此处返回总目录 240 搜索行有序、列有序的二维数组
一、搜索整体有序的二维数组
【题目】
【方法一】 整个数组是从小到大排列的,可以看成是一行的有序数组,对有序数组进行查找可以通过二分查找法完成。
代码:
结果:
时间复杂度:log(m*n)
【方法二】 首先看第一列,找到第一个比target小的元素。则这个元素所在的行就是可能出现target的行。然后在这一行使用二分查找。
代码:
结果:
时间复杂度:m+log(n) 第二种方法的时间要慢一点。
【方法三】 方法二中找第一个比target小的元素使用的是顺序查找的方法,其实我们也可以使用二分查找来做。这样就有了方法三。 首先二分查找第一列,找到第一个比target小的元素。然后再这个元素所在的行再进行二分查找。 这就有点想分块查找的意思了。块内有序,块间有序。
怎么通过二分查找法查找第一个小于等于target的元素,见我的另一篇博客:《二分查找法及延伸》
代码:
结果:
时间复杂度:log(m)+log(n)
【方法四】 比如数组: [[1 , 3, 5, 7], [10,11,16,20], [23,30,34,50], [56,60,66,70]]
首先看第一行最后一个元素7,如果7比target小,说明第一行的所有元素都比target小,就可以排除第一行。如果7比target大,说明最后一列所有元素都比target大,就可以排除最后一列。
代码:
结果: 时间复杂度:m+n
【总结】 这四种方法的时间复杂度分别为 log(m*n) 、m+log(n)、log(m)+log(n)、m+n 因为log(m*n) = log(m)+log(n)。所以方法1,3一样好。都是log这个级别。由于代码1简洁一些,所以排在第一吧。 方法2,4都是线性级别。2要好于4。
因此四种方法排名为: 1 >= 3 > 2 > 4
方法4只利用了行递增、列递增的信息,没有用到整体有序这个信息,所以最慢也正常。但是这种方法也挺巧妙的,还是要会。
二、搜索行有序、列有序的二维数组
【题目】
比上一个题目条件放宽了,不再要求整体有序。只要求每一行递增,每一列递增。 那怎么办呢? 上题的方法一,显然不能用,因为整体无序。 方法二三,也不能用,因为一个数可能出现在好几行的位置。 方法四可以用。
【方法一】 即上题的方法四。 比如数组: [[1, 3, 5, 7], [4,11,16,20], [8,12,18,40], [9,17,32,60]]
首先看第一行最后一个元素7,如果7比target小,说明第一行的所有元素都比target小,就可以排除第一行。
如果7比target大,说明最后一列所有元素都比target大,就可以排除最后一列。
代码:
结果:
【方法二】 使用二分查找的思想,但是比较麻烦。每次排除1/4的内容。 每次考虑矩阵最中间的元素。 如果这个元素比target小,说明左上角的四分之一(红色框框)都不需要找了,只需要考虑右上角、右下角和左下角的(蓝色框框)即可。 如果这个元素比target大,说明右下角的四分之一(红色框框)都不需要找了,只需要考虑左上角、右上角和左下角的(蓝色框框)即可。
代码:
结果:
效果不太理想。
|