问题:
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
.
解决:
① 折半查找。时间复杂度为:log2(n)
class Solution {//15ms
public boolean searchMatrix(int[][] matrix, int target) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0){
return false;
}
int m = matrix.length;
int n = matrix[0].length;
int left = 0;
int right = m - 1;
while(left < right){//二分查找目标值可能所在行的下限
int mid = (right - left) / 2 + left;
if (target < matrix[mid][0]){
right = mid - 1;
}else if (target > matrix[mid][0]){
left = mid + 1;
}else{
return true;
}
}
for (int i = 0;i <= right;i ++){
int start = 0;
int end = n - 1;
while(start <= end){
int mid = (end - start) / 2 + start;
if (target > matrix[i][mid]){
start = mid + 1;
}else if (target < matrix[i][mid]){
end = mid - 1;
}else{
return true;
}
}
}
return false;
}
}
② 分治法。观察矩阵数字的特点:左下角的18,往上所有的数变小,往右所有数增加,那么我们就可以和目标数相比较,如果目标数大,就往右搜,如果目标数小,就往左搜。这样就可以判断目标数是否存在。当然我们也可以把起始数放在右上角,往左和下搜,停止条件设置正确就行。
class Solution {//14ms
public boolean searchMatrix(int[][] matrix, int target) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0){
return false;
}
int m = matrix.length - 1;
int n = matrix[0].length - 1;
int i = m;
int j = 0;//从左下角开始遍历
while (i >= 0 && j <= n){
if (target == matrix[i][j]){
return true;
}else if (target < matrix[i][j]){
i --;
}else{
j ++;
}
}
return false;
}
}