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, 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
.
思路分析:
方法①:若忽视有序这个条件,我们可以直接进行暴力搜索,去检索每一个数组元素。时间复杂度为O(n^m)
public boolean searchMatrix(int[][] matrix, int target) {
//validate
if (null == matrix || matrix.length == 0){
return false;
}
//暴力搜寻
for (int i = 0;i< matrix.length;i++){
for (int j = 0;j<matrix[i].length;j++){
if (matrix[i][j] == target){
return true;
}
}
}
return false;
}
方法②:方法一在数据量很小的时候还是效率还行,但数据量一大就不行了。需要利用有序这个条件,有序的数组自然会想到利用二分查找。所以我们可以在每一行进行二分查找,这样时间复杂度就变为O(nlogm)
public boolean searchMatrix(int[][] matrix, int target) {
//validate
if (null == matrix || matrix.length == 0){
return false;
}
for (int i = 0;i< matrix.length;i++){
if (binarySearch(matrix,target,i) != -1){
return true;
}
}
return false;
}
/**
* 二分查找
*/
public static int binarySearch(int[][] nums,int target,int row){
int left = 0,right = nums[row].length-1;
while (left <= right){
int mid = (left + right) >>> 1;
if (nums[row][mid] == target){
return mid;
} else if (nums[row][mid] < target){
left = mid +1;
} else{
right = mid-1;
}
}
return -1;
}
方法③:利用二分查找的思想,可以从这个二维数组的右上角(也可以从左下角开始检索)开始进行检索,若目标target小于当前元素,则列column--;若target大于目标元素,则row++。这样时间复杂度就变为了O(n+m)
public boolean searchMatrix(int[][] matrix, int target) {
//validate
if (null == matrix || matrix.length == 0){
return false;
}
int row = 0,column = matrix[0].length-1;
while (row < matrix.length && column >= 0){
if (matrix[row][column] == target){
return true;
} else if (matrix[row][column] > target){
column--;
} else{
row++;
}
}
return false;
}