这道题是《剑指offer》38页面试题3(二维数组查找)。
这道题书中给出的解法是从右上角开始,每次都剔除一行或一列。受二分查找启发,我的解法是从二维数组正中间位置开始:
设要查找的数为t,当前检查的数组中的数是r。如果t>r, 则剔除的是四分之一个方形(图中灰色区域)。
下一步再从剩下的白色区域的中心查找(递归)。那么下一步如果t>r,剔除区域则为下图中的深红色区域。
这样每一步剔除的都是很大的一块区域(取决于中心点的选择),比剔除一行或一列要大(当n比较大的时候)。对于两种解法来说,总的剔除面积都是n,如果每一步剔除的面积大,那么步数肯定少。所以我的解法步数要比书中的少。
启示:
1.剔除思想。从解空间中剔除不适合的解。剔除之后得到的缩小的解空间,可以用递归。
2.递归。一开始我没有用递归,而是比较直白的想法:由一个点得到两条边,再检查两条边上的每一个点,再探讨。这样的方法是比较麻烦的。取代这样麻烦的方法,往往是递归,发现结构相似的子问题,也就是动态规划思想。
回顾这个解法,实际上是二分查找的二维版本。可以想到二分查找的本质:找到解空间的中心点,比较,根据解空间元素排列规则,缩小解空间,再从缩小后的解空间中进行递归。中心点的选择取决于排列规则。怎样可以称之为中心点?就是被剔除的解空间的期望(平均大小)要达到最大,比如数组的二分之一,比如图中四分之一的面积。