题目
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:
- Integers in each row are sorted in ascending from left to right.
- Integers in each column are sorted in ascending from top to bottom.
Example:
Consider the following matrix:
1 | [ |
Given target = 5
, return true
.
Given target = 20
, return false
.
解法一
拿到题目一看是查询类的,先暴力解了再说,解法就是两层循环遍历找到值。实现如下:
1 | bool searchMatrix(vector<vector<int>>& matrix, int target) { |
容易看出,这样做的复杂度达到了O(m*n)(m、n对应矩阵的行和列),肯定是不能够让人满意的。
解法二
接下来有哪些地方可以改进的呢?注意这个二维矩阵,暴力求解的时候对每一行是直接顺序扫描,那么这里可以改成对一行进行二分查找,这样一来复杂度可以减少到O(m*logn),实现如下:
1 | bool bisearch(vector<int>& line, int head, int tail, int target){ |
解法三
按照上一个解法提交后我发现成绩还是不尽人意(运行时间在所有成功提交中在中间的位置),那么还能怎么改进呢?思考了许久后,我发现是自己一开始就陷入思维定势了,因为这道题类型属于divide and conquer,所以就一直想着二分,其实并不一定要这么做。
重点是要分析透彻这个矩阵的特点,它的每一行、列的元素都是按从小到大的顺序排列好的,所以每个元素的左边元素都比它小,下面元素都比它大,那么只需要从第一行最右元素开始比较,若比target小就向下移动一位(这一行剩下的不需要查找了),若比target大就向左移动一位,这样若矩阵中存在target那么肯定能够找到。其实从最后一行第一个元素开始也可以,原理是一样的。
实现如下:
1 | bool searchMatrix(vector<vector<int>>& matrix, int target) { |
值得一提的是,这样完成的复杂度最差情况下为O(m+n)。