题目来源:力扣
题目描述:
编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:
- 每行中的整数从左到右按升序排列。
- 每行的第一个整数大于前一行的最后一个整数。
审题:
由于矩阵的特性,我们将其按行展开便可得到一维的按升序排序的数组,因此使用标准的二分搜索方法以时间复杂度O(lgM+lgN)解决,其中M为矩阵行数,N为矩阵列数.这种方法很自然也很容易便能想到,实现起来也不难.
参考其他人的题解,看到有人提到<<剑指offer>>一书提供了另一种更简洁也更高效的方法.我们前面的第一种方法是将矩阵转化为我们较熟悉的一维数组方法.这种方法则充分利用了矩阵的二维特性,使得时间复杂度为O(M+N).其具体思路如下:
从矩阵右上角开始搜索,如果当前值大于目标值,则目标值应该向同一行左侧搜索,我们将当前列数减一,行数不变.如果当前值小于目标值,则目标值应该向下一行搜索.我们将行数+1,列数不变.不难理解,从起点到目标点的搜索路径相当于为从起点所在行先到达目标值所在行,在由最后一列向左搜索.因此最坏情况下,搜索路径即为从右上角到左下角的路径,长度为(M+N).
java算法实现:
1.
class Solution {
//将二维坐标转化为一维坐标
private int twoDimFlattern(int x, int y, int[][]matrix){
return x * matrix[0].length + y;
}
//将一维坐标转化为二维坐标
private int[] oneDimExpand(int x, int[][]matrix){
int[] loc = new int[2];
loc[0] = x / matrix[0].length;
loc[1] = x % matrix[0].length;
return loc;
}
public boolean searchMatrix(int[][] matrix, int target) {
if(matrix == null || matrix.length == 0)
return false;
int lo = 0;
int hi = twoDimFlattern(matrix.length-1, matrix[0].length-1, matrix)+1;
while(lo < hi){
int mid = lo + (hi - lo) / 2;
int[] loc = oneDimExpand(mid, matrix);
if(matrix[loc[0]][loc[1]] == target)
return true;
else if(matrix[loc[0]][loc[1]] < target)
lo = mid+1;
else
hi = mid;
}
return false;
}
}
2.
class Solution {
//从右上角开始搜索
public boolean searchMatrix(int[][] matrix, int target) {
if(matrix == null || matrix.length == 0)
return false;
int row = 0;
int col = matrix[0].length-1;
while(row < matrix.length && col >= 0){
if(matrix[row][col] == target)
return true;
else if(matrix[row][col] > target)
col--;
else
row++;
}
return false;
}
}
简洁优美的代码竟能同时达到性能上的更优!