/** * 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 from left to right. * The first integer of each row is greater than the last integer of the * previous row. * * For example, * * Consider the following matrix: * * [ * [1, 3, 5, 7], * [10, 11, 16, 20], * [23, 30, 34, 50] * ] * Given target = 3, return true. * * Tags: Array, Binary Search */ class Search2DMatrix { public static void main(String[] args) { Search2DMatrix s = new Search2DMatrix(); int[][] matrix = { {1, 3, 5, 7}, {10, 11, 16, 20}, {23, 30, 34, 50}}; System.out.println(s.searchMatrix(matrix, 0)); System.out.println(s.searchMatrix(matrix, 1)); System.out.println(s.searchMatrix(matrix, 2)); System.out.println(s.searchMatrix(matrix, 11)); System.out.println(s.searchMatrix(matrix, 15)); System.out.println(s.searchMatrix(matrix, 34)); System.out.println(s.searchMatrix(matrix, 35)); System.out.println(s.searchMatrix(matrix, 50)); System.out.println(s.searchMatrix(matrix, 51)); System.out.println(s.searchMatrix(matrix, 100)); } /** * Binary search to locate row, then binary search in a row * O(logm + logn) */ public boolean searchMatrix(int[][] matrix, int target) { if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return false; int left = 0; int right = matrix.length - 1; int mid; while (left <= right) { mid = left + (right - left) / 2; if (matrix[mid][0] == target) return true; else if (matrix[mid][0] > target) right = mid - 1; else left = mid + 1; } // row index is left - 1 if (left - 1 < 0 || left - 1 >= matrix.length) return false; int row = left - 1; left = 0; right = matrix[row].length - 1; while (left <= right) { mid = left + (right - left) / 2; if (matrix[row][mid] == target) return true; else if (matrix[row][mid] > target) right = mid - 1; else left = mid + 1; } return false; } /** * n * m matrix convert to an array => matrix[x][y] => a[x * m + y] * an array convert to n * m matrix => a[x] =>matrix[x / m][x % m]; * * disadvantage: 1. m * n may overflow 2. / and % are expensive */ public boolean searchMatrixBest(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 * n - 1; int mid; while (left <= right) { mid = left + (right - left) / 2; if (matrix[mid / m][mid % m] == target) return true; else if (matrix[mid / m][mid % m] > target) right = mid - 1; else left = mid + 1; } return false; } }