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.
假设存在这样一个矩阵,该矩阵从左至右以及从上到下的值均为由小到大排列。如今输入一个目标值,要求判断该矩阵中是否存在该值。面试
直观的来看咱们确定会从左上角开始判断,若是当前的值比目标值大,那么结束返回该值不存在,而若是当前的值比目标值小,则咱们顺着行或是列继续查找。
代码以下:微信
int column = 0; int row = 0; public boolean searchMatrix(int[][] matrix, int target) { if(matrix==null || matrix.length == 0) return false; row = matrix.length; column = matrix[0].length; return searchMatrix2(matrix, target, 0, 0, row-1, column-1); } //超时 public boolean searchMatrix(int rowIndex, int columnIndex, int target, int[][] matrix){ if(rowIndex>=row || columnIndex>=column)return false; if(matrix[rowIndex][columnIndex] > target) return false; else if(matrix[rowIndex][columnIndex] == target) return true; return searchMatrix(rowIndex+1, columnIndex, target, matrix) || searchMatrix(rowIndex, columnIndex+1, target, matrix); }
固然了,这个方法不出意外,超时了~ide
咱们采用二分法的思想,将矩阵分解为更小的矩阵从而每一次筛选确保可以去除掉一个子矩阵范围。咱们以题目中的矩阵做为例子:spa
找到当前矩阵的中心下标,这里即为matrix[2][2]
上的9
,鉴于目标值5
比9小,所以咱们将矩阵分解为以下四块,并排除掉右下角的子矩阵,而后在剩余的三个矩阵中继续遍历。code
[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]
若是目标值比当前中心值更小,那么咱们就能够排除左上角矩阵。教程
这个思路的代码以下:递归
int column = 0; int row = 0; public boolean searchMatrix2(int[][] matrix, int target) { if(matrix==null || matrix.length == 0) return false; row = matrix.length; column = matrix[0].length; return searchMatrix2(matrix, target, 0, 0 ,row-1, column-1); } public boolean searchMatrix2(int[][] matrix, int target, int leftRow, int leftColumn, int rightRow, int rightColumn){ if(leftRow==rightRow && leftColumn==rightColumn) return matrix[leftRow][leftColumn] == target; else if(leftRow > rightRow || leftColumn > rightColumn) return false; else if(target < matrix[leftRow][leftColumn] || target > matrix[rightRow][rightColumn]) return false; int midRow = (leftRow + rightRow) / 2; int midColumn = (leftColumn + rightColumn )/2; int midValue = matrix[midRow][midColumn]; if(midValue == target) return true; else if(target < midValue){ return searchMatrix2(matrix, target, leftRow, leftColumn, midRow-1, rightColumn) || searchMatrix2(matrix, target, midRow, leftColumn, rightRow, midColumn-1) ; }else{ return searchMatrix2(matrix, target, leftRow, midColumn+1, rightRow, rightColumn) || searchMatrix2(matrix, target, midRow+1, leftColumn, rightRow, midColumn); } }
当咱们从左上角开始遍历时,咱们会发现一次比较能够提供的信息实在是太少了。咱们能够试着从左下角开始遍历看看是否可以提供更多的信息。仍是以题目中给的矩阵做为例子:ip
从左下角比较的时,一旦目标值比当前值大,咱们就将下标向右移动,一旦目标值比当前值小,咱们就将下标向上移动。咱们能够看见,由于从左下角开始遍历,那么每次的遍历都确保了咱们的值必定比当前下标左侧的全部列的值大,也比当前下标下方全部行的值都大。从而咱们能够将目标值锁定在左上方的子矩阵上。ci
这里给出的代码是从右上角开始遍历的,以下:开发
public boolean searchMatrix3(int[][] matrix, int target) { if(matrix == null || matrix.length < 1 || matrix[0].length <1) { return false; } int col = matrix[0].length-1; int row = 0; while(col >= 0 && row <= matrix.length-1) { if(target == matrix[row][col]) { return true; } else if(target < matrix[row][col]) { col--; } else if(target > matrix[row][col]) { row++; } } return false; }
想要了解更多开发技术,面试教程以及互联网公司内推,欢迎关注个人微信公众号!将会不按期的发放福利哦~