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.
For example,
Consider the following matrix:
[ [1, 4, 7, 11, 15], [2, 5, 8, 12, 19], [3, 6, 9, 16, 22], [10, 13, 14, 17, 24], [18, 21, 23, 26, 30] ]
Given target = 5
, return true
.
Given target = 20
, return false
.
这道题的大意是:给定一个每行每列都是严格递增的矩阵,查找一个数是否在矩阵里面。
我想到的是从左上角开始找,对于每个节点都分三种情况>=<,这样分开遍历整个矩阵,但这种做法比直接遍历整个矩阵还要费时,因为有些节点可能会多次访问。果然不出所料,TLE了。
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
if ( ! matrix.size() || ! matrix[0].size() )
return false ;
int m = matrix.size() , n = matrix[0].size() ;
return search ( 0 , 0 , m , n , matrix , target ) ;
}
bool search ( int c , int l , int m , int n , vector<vector<int>>& matrix , int target )
{
if ( ! ( c < m && l < n ) )
return false ;
if ( matrix[c][l] == target )
return true ;
if ( matrix[c][l] > target )
return false ;
return ( search ( c + 1 , l , m , n , matrix , target ) || search ( c , l + 1 , m , n , matrix , target ) ) ;
}
};
从前往后找必定会遇到多个分叉,并且分叉还会相交,这明显不是明智之举。但从后往前找呢?右下角往前推也会遇到类似的问题。既然从前往后和从后往前都不行,不妨试试从边角(右上角或左下角)开始找,我们发现,这样找虽然也是每个节点分三种情况讨论,但最终只会生成一个分叉,比如从右上角开始,每次查找要么向左要么向下,最坏的查找时间复杂度为O(m+n),这样比遍历整个矩阵简单多了,也能体现这种特殊矩阵的优越性。
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
if ( ! matrix.size() || ! matrix[0].size() )
return false ;
int i = 0 , j = matrix[0].size() - 1 ;
while ( i < matrix.size() && j >= 0 )
{
int num = matrix[i][j] ;
if ( num == target )
return true ;
else if ( target > num )
i ++ ;
else
j -- ;
}
return false ;
}
};