专栏 | 九章算法
网址 | www.jiuzhang.com
题目描述
在一个 m*n 整数矩阵中找到指定值 target。
这个整数矩阵有如下性质:
- 每行从左到右数值递增
- 每列从上到下数值递增
Example:
有如下矩阵:
指定值 target = 5,返回True。
指定值 target = 20,返回False。
解题思路分析
1. 简单粗暴法:扫描整个矩阵,找出要找的指定值。算法复杂度:O(m*n)。
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相关练习题
推荐阅读
- 12 个 tips 教你搞定 onsite!
- 25 个 questions, 教你向面试官提问!
- 10 个 tips 教你搞定电面!
- 北美IT企业fulltime薪资大曝光
- IT 简历模板大放送 | 《如何写好技术简历》讲座精华总结
- 面试遇到做过的题怎么办?
- 冷冻期大揭秘 | Google、FB、Amazon、Linkedin冷冻期
- 面试前如何了解一家IT企业?试试官方技术博客!
- Google晋升机制 | 大公司如何升级打怪, 获得晋升?
欢迎关注我的微信公众号:九章算法(ninechapter)。
精英程序员交流社区,定期发布面试题、面试技巧、求职信息等
