专栏 | 九章算法
网址 | www.jiuzhang.com程序员
题目描述 面试
在一个 m*n 整数矩阵中找到指定值 target。算法
这个整数矩阵有以下性质:数组
Example:微信
有以下矩阵:
优化
指定值 target = 5,返回True。
指定值 target = 20,返回False。3d
解题思路分析 code
1. 简单粗暴法:扫描整个矩阵,找出要找的指定值。算法复杂度:O(m*n)。cdn
2. 能不能优化?必须能够!根据矩阵的性质,会联想到二分查找。要如何让矩阵像数组那样每次减小一部分不须要进行比较的呢?咱们分析一下二分查找算法,之因此每次能够舍弃掉一半,是由于咱们经过中间的一个数(split_num)把数组分红了两部分,左边部分都不大于 split_num,右边部分都不小于 split_num。而后经过比较 target 跟 split_num 的大小能够知道target在左边仍是右边,从而舍弃掉另一半。注意:切分后,左右两部分跟切分前同样都是一个数组,因此咱们才能继续按照一样的标准对被选取的那一半进行处理。面试技巧
1)如今数组变成了矩阵,要如何选取这个 split_num 呢?因为在数组中,咱们取的是最中间的元素做为 split_num,那么在这里咱们尝试几个处于矩阵中特殊位置、有可能切分矩阵的元素:
A. 矩阵中心位置:以上面为例,取 matrix[2][2] = 9 这个元素,若 target < 9 那么 target 在左上角的这个矩阵里;但若是 target > 9,那么 target 可能在 matrix[2][2] 的右边,也可能在 matrix[2][2] 的下边,这两部分合起来造成一个相似 J 的形状,并非一个矩阵,那么接下来咱们便不能按照一样的标准进行切分了。与上面说的二分查找算法的想法相违背。
B. 矩阵对角线位置:若是是在对角线上任意取一个元素,那么状况与上述一致,因此这个不可行。那尝试对角线顶点元素?左上角 matrix[0][0] 和右下角 matrix[4][4] 的这两个元素,由于是最小值和最大值,因此并不能起到切分的做用,一样舍弃。而左下角 matrix[4][0] 和右上角 matrix[0][4] 这两个元素呢?以左下角 matrix[4][0] = 18 为例,若 target < 18,那么 target 在 matrix[4][0] 上方的这个矩阵里;若 target > 18,那么 target 在 matrix[4][0] 右边的这个矩阵里。无论 target 在哪一边,被选取的那部分都是一个矩阵!那咱们就能继续在被选取的矩阵里比较其左下角元素和 target 的大小,进而继续缩小 target 所在的矩阵,直到找到 target!(同理,右上角这个元素也是可行的。)
2) 由此,咱们能够用“左下角元素”或“右上角元素”做为 split_num(我这里就选择了左下角元素):
a. 若是 target == 左下角元素(当前位置),那么已经完成任务!
b. 若是target > 左下角元素 matrix[m][0],那么与 matrix[m][0] 同一列的元素全都小于 target, target 位于右边的矩阵 matrix[0..m][1..n]。
c. 若是 target < 左下角元素 matrix[m][0],那么与 matrix[m][0] 同一行的元素全都大于 target, target 位于上边的矩阵 matrix[0..m-1][0..n]。
d. 这个算法的复杂度是 O(m+n)。
参考代码
面试官角度分析
这道题若是可以答案O(m+n)就能够拿到offer。
LintCode相关练习题
推荐阅读