《剑指Offer》面试题3:二维数组中的查找
《剑指Offer——名企面试官精讲典型编程题》
作者:何海涛
一、书上原题再现
面试题3:二维数组中的查找
题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。
请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
二、涉及的知识点
三、解题过程
首先一看到数组,就会下意识的想到遍历,就是挨个比较,看看要查找的数在不在里面,遍历虽然是万能的,但是一个一个的比较,未免太过麻烦。不妨找找有没有其他的方法,如果实在是找不到,最后再用遍历的方法。
这道题比较特殊,特殊在数字是有序的,最小的数在左上角,最大的数在右下角,如下图所示:
假如要查找9是否在二维数组内,我们可以选择从右上角开始查找,发现9>4,因为从左到右递增,9都比4这一行最右边的一个数大了,所以这时候就可以忽略4左边的所有数了,直接往下走进行比较(相当于删掉一整行),发现9>8,同理,继续往下(相当于删掉一整行),发现9<12,说明9有可能在12的左边,往左走进行比较,发现9<11,同理,继续往左,发现9<10,继续往左,发现9=9,返回结果为true,说明9在该二维数组中。
如下图所示:
对上面这段话的一开始有个疑问,为什么要从右上角开始进行比较,能不能换个地方?
答案是:能。
发现右上角往左是递减,往下是递增。
相似左下角往右是递增,往上是递减。
所以左下角也可以当做入手点,能够实现比较一个数就删掉一整行。
还有左上角和右下角,这两个不能当做入手点,以左上角为例,最初数字1位于数组的左上角,因为这个数组是往右和往下两个方向递增的,我们要查找9,那么就无法做到删掉一行,因为9既有可能在1的右边,也有可能在1的下边,右下角道理相似。
四、调试步骤
使用MyEclipse进行调试
上图为示意图的代码实现:
一、 先把flag设为false,默认不存在。
二、 默认数组每行的列数都相等,所以可以
用rows=array.length来代表行数,
用columns=array[0].length来代表列数。
三、 row 和 column 来控制比较的切入点为右上角,
所以row=0,column=columns-1,减一是因为数组下标索引从0开始而不是从1开始。
我的完整测试代码:
https://github.com/littlecurl/CodingInterviews
五、总结
因为这道题的特殊性,所以有特殊解法的存在。与遍历的方法相比,这样一次删掉一行或一列的方法显然要快速的多。
六、声明与致谢
本题源代码请移步《剑指Offer》作者何海涛的GitHub:https://github.com/zhedahht/CodingInterviewChinese2
参考文章:(每篇文章我都会去点赞,好的文章就应该公诸于世,大家共同学习)
GitHub博客:
Littlecurl的《二维数组中的查找》: