Microsoft Interview Question
Software Engineer / DevelopersCountry: India
Interview Type: In-Person
binarySearch on 2D matrix:
#include <stdio.h>
#include <stdlib.h>
int rows = 50;
int cols = 50;
int** matrix = NULL;
int search_matrix(int start_row, int start_col, int end_row, int end_col,
int search_term) {
int returnValue = -1;
int mid_row = (start_row + end_row) / 2;
int mid_col = (start_col + end_col) / 2;
if (start_row > end_row || start_col > end_col || end_row < start_row
|| end_col < start_col || search_term < matrix[0][0])
return -1;
if (matrix[mid_row][mid_col] == search_term) {
printf("\nFound %d at Row = %d Column = %d\n", search_term, mid_row,
mid_col);
return mid_row;
}
if (matrix[mid_row][start_col] <= search_term
&& matrix[mid_row][cols] >= search_term) {
// we have found our row
if (matrix[mid_row][start_col] <= search_term
&& matrix[mid_row][mid_col] >= search_term) {
start_row = mid_row;
//start_col = 0;
end_row = mid_row;
end_col = mid_col;
}
else if (matrix[mid_row][mid_col] < search_term
&& matrix[mid_row][cols] >= search_term) {
start_row = mid_row;
start_col = mid_col;
end_row = mid_row;
end_col = cols;
}
returnValue = search_matrix(start_row, start_col, end_row, end_col,
search_term);
} else if (matrix[mid_row][0] > search_term) {
end_row = mid_row;
end_col = cols;
start_row = 0;
//start_col = 0;
returnValue = search_matrix(start_row, start_col, end_row, end_col,
search_term);
} else if (matrix[mid_row][0] < search_term) {
start_row = mid_row + 1;
//start_col = 0;
end_row = rows;
end_col = cols;
returnValue = search_matrix(start_row, start_col, end_row, end_col,
search_term);
}
return returnValue;
}
int main(int argc, char** argv) {
int i = 0, j = 0, counter = 0;
matrix = (int**) malloc(sizeof(int) * rows);
for (i = 0; i < rows; i++) {
matrix[i] = (int*) malloc(sizeof(int) * cols);
}
// initialize matrix
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++)
matrix[i][j] = counter + j;
counter = matrix[i][cols - 1] + 1;
}
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++)
printf("%d ", matrix[i][j]);
printf("\n");
}
cols = cols - 1;
rows = rows - 1;
int searchTerm = 2423;
int index = search_matrix(0, 0, rows, cols, searchTerm);
if (index == -1)
printf("\n%d not present in matrix\n", searchTerm);
return EXIT_SUCCESS;
}
@manikantansubramanyam: what does this code do??? above code works fine, its just 5 lines of code!!!
since the matrix contains sorted numbers, its more efficient to not look at every possible index of the matrix. Looking at every index will make the search O(n^2). but doing a binary search would eliminate rows and cols where our search term is not expected to be. Hence, the efficiency of this would be O(log n).. thats the advantage.
This wouldn't work for an input like
{10, 20, 30, 40},
{15, 25, 35, 45},
{26, 31, 38, 48},
{32, 34, 39, 50} where the value at a particular i,j can be greater than the range for the previous row and vice versa.
I'm not able to come up with something better than O(n) [ check for the last value in the row approach and then do a binary search on the row which would result in O(n) + O(log(n))]. Can someone elaborate on a better method.
the above code would work on inputs where the matrix sequence is strictly increasing across rows, columns and adjacent rows.
@sujith for your input, i'm not sure how to find a row and do a binary search in [O(n) + O(log(n))] time. lets say we're searching for the number 38, now as per your logic, you'll first loop over all the rows comparing the value of matrix[i][0] and matrix[i][n-1] with 38. For each such satisfying row, you will need to do a binary search to get the actual column of 38 (if it exists in that row). This will take you O(n*log(n)) time in the worst case. For example, if we search for 38, we'll have to do a binary search on Row 1(assuming the row count starts at Row 0), and Row 2 before we get the desired data.
Thanks @jester. realized it wouldn't work either..
I guess the best solution here is to eliminate 1/4th of the matrix depending on whether the element is greater than the mid element and recursively keep finding the element in the remaining 3 sub matrices..
A very neat solution would be to start at the bottom left(or top right position) and have counters to step up and step right. This would be O(m-1 * n-1) which is not as good as the recursive approach
The above code wouldn't work because - for example - if we find a row where the first element < target and last element > target, we haven't necessarily found the row containing the element - it could be in another row altogether!
@manikantansubramanyam: the above code is o(m+n). Actually, it will take m+n steps in the worst case.
Hey....
Use Binary Search Algorithm modified for 2D Array. It will work at O(log n), for an array of mxn or nxm, where n>m.
Pseudo code according to me:
tuple (x,y) = (0,0).
tuple (m,n) = (m,n)
then check if a[0][m/2] > num and [n/2][0] >num
decide accordingly and change the tuples correspondingly .
recursively search.
basically my logic is to half the matrix in each recursive call.
A O(log(n)) solution:
int binarySearch(int n, vector<int> &A, int s, int e) {
if(s >= e) return s;
auto m = (s + e) / 2;
auto v = A[m];
if(v == n) return m;
if(v < n) return binarySearch(n, A, m + 1, e);
return binarySearch(n, A, s, m - 1);
}
struct Point {int i; int j; Point(int i_, int j_){i=i_;j=j_;}};
Point find(int n, vector<vector<int>> &A) {
auto size = A.size();
int row = 0, col = 0, prevCol = 0, prevRow = 0;
while(A[row][col] < n) {
if(A[row][size-1] >= n) {
col = binarySearch(n, A[row], col, size - 1); //find the cell just less than the search value in the current row
if(A[row][col] > n) { //binary search returned the higher cell, so decrement by 1
col--;
}
}
if(A[size - 1][col] >= n) {
vector<int> column;
for(auto r = row; r < size; r++) {
column.push_back(A[r][col]);
}
row = binarySearch(n, column, 0, size - 1 - row) + row;//find the cell just less than the search value in the current column
if(A[row][col] > n) {//binary search returned the higher cell, so decrement by 1
row--;
}
}
if(col == prevCol && row == prevRow) {//no movement -> not found
break;
}
prevRow = row; prevCol = col;
}
if(A[row][col] != n) return Point(-1, -1);
return Point(row, col);
}
The comments made it less readable. Here a version with the comments
int binarySearch(int n, vector<int> &A, int s, int e) {
if(s >= e) return s;
auto m = (s + e) / 2;
auto v = A[m];
if(v == n) return m;
if(v < n) return binarySearch(n, A, m + 1, e);
return binarySearch(n, A, s, m - 1);
}
struct Point {int i; int j; Point(int i_, int j_){i=i_;j=j_;}};
Point find(int n, vector<vector<int>> &A) {
auto size = A.size();
int row = 0, col = 0, prevCol = 0, prevRow = 0;
while(A[row][col] < n) {
if(A[row][size-1] >= n) {
col = binarySearch(n, A[row], col, size - 1);
if(A[row][col] > n) {
col--;
}
}
if(A[size - 1][col] >= n) {
vector<int> column;
for(auto r = row; r < size; r++) {
column.push_back(A[r][col]);
}
row = binarySearch(n, column, 0, size - 1 - row) + row;
if(A[row][col] > n) {
row--;
}
}
if(col == prevCol && row == prevRow) {
break;
}
prevRow = row; prevCol = col;
}
if(A[row][col] != n) return Point(-1, -1);
return Point(row, col);
}
- arham December 30, 2011