面试题:查找有序的二维数组中的元素

summary

:

《剑指Offer》里面看到的一道题,很有意思。

题目

给定一个二维数组,每一行按照从左到右递增排好序了,每一列按照从上到下递增排好序 了,写一个函数,输入这个二维数组和一个整数,判断数组中是否含有这个整数。

分析

抽象问题变具体。考虑下面的二维数组:

1 2 8 9

2 4 9 12

4 7 10 13

6 8 11 15

要查找某个整数,关键是"夹逼",不断缩小范围,因为是有序的。从哪里开始呢?首先, 左上角和右下角是肯定不行,因为这两个地方不能"夹逼"。以左上角为例,往右边是变 大,往下边也是变大,当要查找的整数比左上角的整数要大时,该往哪边去呢?所以这里 是不行的,同理,右下角也不行。而右上角却可以,主要是因为那里构成了"夹逼"的条 件。比如,要查找某个数,如果比9小,则9所在的列不用看了,因为在9下面的整数都比 9要大,如果比9大,则9所在的行也不用看了,因为在9左边的整数都比9小。同理,左下 角也是可以的。

这样,我们就可以从右上角开始,一步一步缩小范围了。但是,既然二维数组是有序的, 一步一步来是不是太费时了?想想查找有序的数组时可以利用二分查找,那这里也可以! 但是事实上,二分查找在方形二维数组中效果不是很好。

这是一个经典问题,看 stackoverflow 上的讨论,以及这位大牛提出的 效率高的解法

最简单的解法的代码

::: {.code-include lexer="cpp"} ./search-sorted-2d-array.cpp :::

使用了Boost的单元测试框架,链接的时候要加上 -lboost_unit_test_framework 参数。