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; }
想要了解更多開發技術,面試教程以及互聯網公司內推,歡迎關注個人微信公衆號!將會不按期的發放福利哦~