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
.
============
Analysis:
Original thought includes 2 steps. First find out which row target number probably belongs to, then search the target row. Time complexity of this approach is O(m+n).
public class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int row = matrix.length;
int col = matrix[0].length;
int targetRow = 0;
if(row == 0 || col ==0) return false;
for (int i=0; i<row; i++){
if(target == matrix[i][0]) return true; // found target
// possible element that equal to target would be in i-1 row
if(target < matrix[i][0]) {
// case of target less then the 1st element
if (i == 0) return false;
targetRow = i-1;
break;
}
// if not break or return, then search the last row
targetRow = row-1;
}
for (int i=0; i<col; i++){
// target exist
if(matrix[targetRow][i] == target) return true;
}
// target not exist
return false;
}
}
By checking other available solutions, I found the best way should be using binary search, in which the time complexity is O(log(m+n)). Basic idea of which is that as the m*n matrix is sorted by row and column, we can treat it as a 1D sorted array, then we can apply binary search for this array. Assuming we are examining element m in the 1D array, this element can be referred to the element matrix[m/column][m%column] in the original matrix.
public class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int row = matrix.length;
int col = matrix[0].length;
if(row == 0 || col ==0) return false;
// treat matrix as 1D sorted array
int start = 0;
int end = row*col-1;
while(start<=end){
int m = start+(end-start)/2;// find the middle element of the target range
if(matrix[m/col][m%col] == target) return true;
if(matrix[m/col][m%col] > target) end = m-1;// limit range to start->middle-1
else start = m+1;// limt range to middle+1 to end
}
return false;
}
}