从左下角位置开始搜索
时间复杂度:O(行数+列数)。
想法有点像二分法,大了往一个方向找,小了往另一个方向找。由于矩阵横向和纵向都是递增,如果从(0,0)位置开始找,往右和往下都是增大,因此不知道实际上要往哪个方向找。但是如果以左下角位置为搜索起点,则向右是递增,向上是递减,就可以用类似二分法的方式来解决这个问题。
我们知道从矩阵的一个位置到达另一个位置都可以用若干次横向移动和若干次纵向移动,因此我们只要保证在搜索的过程中横移和纵移一个是增大一个是减小即可,因此从左下角和右上角开始搜索都可以,而从左上角和右下角开始搜索则不行。
public boolean searchMatrix(int[][] matrix, int target) {
int m=matrix.length,n=matrix[0].length;
int i=m-1,j=0;
while(i>=0&&j<n){
if(matrix[i][j]==target) return true;
else if(matrix[i][j]<target) j++;
else i--;
}
return false;
}
两个方向二分
这种解法在矩阵行数和列数相差很大的时候比较有效。
private boolean searchRow(int[][] matrix,int i,int target){
int l=0,r=matrix[0].length-1,mid;
while(l<=r){
mid=(l+r)/2;
if(matrix[i][mid]==target) return true;
else if(matrix[i][mid]<target) l=mid+1;
else r=mid-1;
}
return false;
}
private boolean searchColumn(int[][] matrix,int i,int target){
int l=0,r=matrix.length-1,mid;
while(l<=r){
mid=(l+r)/2;
if(matrix[mid][i]==target) return true;
else if(matrix[mid][i]<target) l=mid+1;
else r=mid-1;
}
return false;
}
public boolean searchMatrix(int[][] matrix, int target) {
//如果行数小于列数,则二分搜索的次数等于行数;反之等于列数
for(int i=0;i<matrix.length&&i<matrix[0].length;++i){
if(searchRow(matrix,i,target)||searchColumn(matrix,i,target)) return true;
}
return false;
}