# Search in a row wise and column wise sorted matrix

Given an n x n matrix, where every row and column is sorted in increasing order. Given a number x, how to decide whether this x is in the matrix. The designed algorithm should have linear time complexity.

Thanks to devendraiiit for suggesting below approach.

2) Loop: compare this element e with x
….i) if they are equal then return its position
…ii) e < x then move it to down (if out of bound of matrix then break return false) ..iii) e > x then move it to left (if out of bound of matrix then break return false)
3) repeat the i), ii) and iii) till you find element or returned false

Implementation:

```#include<stdio.h>

/* Searches the element x in mat[][]. If the element is found,
then prints its position and returns true, otherwise prints
int search(int mat[4][4], int n, int x)
{
int i = 0, j = n-1;  //set indexes for top right element
while ( i < n && j >= 0 )
{
if ( mat[i][j] == x )
{
printf("\n Found at %d, %d", i, j);
return 1;
}
if ( mat[i][j] > x )
j--;
else //  if mat[i][j] < x
i++;
}

return 0;  // if ( i==n || j== -1 )
}

// driver program to test above function
int main()
{
int mat[4][4] = { {10, 20, 30, 40},
{15, 25, 35, 45},
{27, 29, 37, 48},
{32, 33, 39, 50},
};
search(mat, 4, 29);
getchar();
return 0;
}

```

Time Complexity: O(n)

The above approach will also work for m x n matrix (not only for n x n). Complexity would be O(m + n).

Please write comments if you find the above codes/algorithms incorrect, or find other ways to solve the same problem.

# Company Wise Coding Practice    Topic Wise Coding Practice

• danny

If we convert this 2D array into 1D row major array then we can apply binary search on that 1D array as elements are sorted So, the time complexity would be O(log(m)+log(n)) but we require space…
Please correct me if I am wrong or also give your comments if above method works fine…

• AlienOnEarth

It will not work. you need to visit every element atleast once to convert 2d to 1d. which means time = o(n*m) and space (n*m)

• Guest

If we convert this 2D array into 1D row major array then we can apply binary search on that 1D array as elements are sorted So, the time complexity would be O(log(m+n)) but we require space…
Please correct me if I am wrong or also give your comments if above method works fine…

• Geek

One simplest way many of you aware is,
If the matrix is n (columns) X m (rows) and n > m.
Then repeat loop linearly for m (rows) and apply binary search on n (columns).
So it would be O(m log n).
But I heard in net that we can achieve with O (log m x n) or O(log m +n) but couldn’t find the code for the same.

• Guest

Not only is the author of this article’s post optimal in that it’s O(N), but the fact that it takes only 2*N comparisons is also optimal. Simply imagine the boundary between two halves of the matrix divided by a specific target value. It might follow the diagonal from the lower left to the upper right, in which case at least N values must be checked. However, it could also hug the left and top sides, or close to them, being closer to 2*N in length. This entire boundary must be checked. Therefore, in the limit as N gets large, 2*N elements must be checked. This answer is as optimal as any we will see, except for mine

My solution is slightly better because for huge matricies, when the whole thing does not fit into cache, I move right when in the same row, rather than left. In my code, the hardware prefetch circuitry will cause my version (scanning starting in the lower left, moving to the upper right) to run faster, because I will have a better cache hit rate.

I win!

• All the guys posting O(log(m)) or O(log(m) + log(n)) solutions above are wrong! The original poster has the optimal answer with the O(N) solution! Consider this matrix:

1 2 3 4 4
2 3 4 4 6
3 4 4 6 7
4 4 6 7 8
4 6 7 8 9

Now do a search for 5. Any single element of the diagonal could be 5 legally. Unless you check them all, you can’t prove it’s not there! Since the diagonal has N elements for an NxN matrix, an optimal algorithm must have at least O(N) comparisons. Any claim of an O(log(N)) is mistaken.

Further, the next diagonal, containing 6’s are also legal locations for a 5 to exist, so clearly 2*N-1 locations must be searched, meaning that the original algorithm posted is exactly optimal in terms of comparisons. The only improvement I would make is starting at the lower left instead of the upper right, since I’d have a better chance of a cache hit due to hardware prefetch algorithms while scanning right instead of left.

Also, the posters who asked about using the middle element and searching the remaining 3 quadrants have a clever algorithm, but it’s slow. You have to compute the number of comparisons for a few matricies to see that picking the middle is a poor choice. The total comparisons looks like:

1 + 3(1 + 3*(1 + 3(… + 3*(1)))…)

For a 2×2:4
For 4×4: 1 + 3*4 = 13 — we already know that the 2×2 takes 4
For 8×8: 1 + 3*13 = 40
For 16×16:121, 32×32:364, 64×64:1,093 …

It’s polynomial, not linear. It’s growing faster than N^1.65. This is much slower than the original solution. In comparison, just doing a binary search on each row takes N*log2(N) comparisons, so the 64×64 would require 64*6 = 384, quite a bit faster than the pick the middle algorithm.

An improvement to the pick the middle algorithm is to do a binary search on the diagonal from the upper left to lower right, and use the two adjacent values spanning the target to eliminate 1/2 of the matrix. This algorithm takes 1/2*N*log2(N) comparisons, which is twice as fast as binary search on each row, though still far from optimal, and if the matrix doesn’t fit into cache, it will thrash memory much worse than a binary search on each row.

Improvements can be made over the original algorithm to improve cache performance. For example, storing the matrix diagonal by diagonal rather than row by row increases the odds of a cache hit a lot for random data. However, by that point, it probably makes more sense to finish sorting the table so that each row contains values greater than the previous rows, and less than the following rows, so you can do the search in O(log(N)). Also, if you know the typical queries will not be middle-ish values, then you can save some time on average with a binary search along the left and bottom edges to find a better starting point, which is faster than starting in the lower-left corner and then scanning up or right for a significant fraction of the edge, but your worst case will then be 2*N + log2(2*N) – 1 comparisons.

• I have written divide-and conquer method to search key in n*n matrix where rows and columns both are sorted ascending.
Algorithm is :-
Go for middle element.
1) If middle element is same as key return.
2) If middle element is lesser than key then
2a) search submatrix on lower side of middle element (half of matrix)
2b) Search submatrix on right hand side.of middle element (up-left quarter)
3) If middle element is greater than key then
3a) search vertical submatrix on left side of middle element (left vertical half)
3b) search submatrix on right hand side. (up-left quarter)

A picture could help it explain better. But code is also easy to understand. Find code at
http://ideone.com/zJ29vW

Can anyone comment is this algo is any better than above simple search; especially for large matrices ?

• Guest

Your algorithm is faster than the versions that recurse on 3 quadrants. At the next level, you eliminate 3/16th with 2 comparisons rather than 3/16ths with 3 comparisons. I expect this 2/3 computation effort to continue, and you should run in about 2/3rds the runtime of the guys that check all 3 quadrants. However, it’s still polynomial rather than linear in time. The original poster’s solution remains the best posted on this thread, other than picking the wrong corner to start from for cache efficiency.

• What is the correct code for binary search method ?

• newCoder

/**
* Given an n x n matrix, where every row and column is sorted in increasing
* order. Given a number x, how to decide whether this x is in the matrix.
* The designed algorithm should have linear time complexity.
*
* @param mat
* @param x
* @return
*/
public static boolean find(int[][] mat, int x) {

int i = 0;
int j = mat[0].length – 1;

while (i = 0) {
if (mat[i][j] == x) {
System.out.println(“”+ i + ” ” + j);
return true;
} else if (mat[i][j] > x) {
j–;
} else {
i++;
}
}
return false;
}

• numid

The solution should be updated as it can be done in O(logM +logN) by appyling binary search for the matrix with a little modifications:
1. search for the middle element of the matrix
2.if the middle elemnt is less than the missing number,search the lower half
else
search the upper half
3. when u get a single row or two rows in which the search is to be performed,
do 1 comparison with the last arr[i][n] to get the row in which the normal binary search will be performed.
the following link have not been commented though,shows the code.
http://ideone.com/s2WvGR

• Lokesh

Is there a middle element if this is not a square matrix ?

• Jiten

Will this work if the rows are not ordered according to their first element?

• Kartik

This may not work for many examples. Here the assumption is wrong. If an element is greater than the middle element, then we can discard half of the matrix, we can only discard, 1/4th of the matrix.

• Varsha Anandani

can someone tell the space complexity also..???

• mahesh

space complexity is O(1). We didn’t use any auxiliary space.

• Pranav

A modified approach, such that moving to down/left occurs in binary fassion.

2) Loop: compare this element e with x
….i) if they are equal then return its position
…ii) e x then move it to left by going to the middle (if out of bound of matrix then break return false)
3) repeat the i), ii) and iii) till you find element or returned false

Time Complexity:O(logn + logm)

• aks

complexity is O(n+m) ……at most in you are going to traverse down all rows and all columns (let’s say when element to find is the first col last element)

• mrn
``` ```
while(l<r)
{
m=(l+r)/2;
if(a[m][0]>x)
r=m-1;
else
if(a[m][col]>x)
l=m+1;
else
break;
}

for(int i=0;i<=col;i++)
if(a[m][i]==x)
cout<<m<<" "<<i<<endl;
``` ```
• algobard

Can you please post the recursive solution (O(n^1.53)) to this problem too?

• Jay

Use binary search,

O(log(column))*O(log(row))

``` ```
/* Paste your code here (You may delete these lines if not writing code) */
``` ```
• Ashish Ranjan Singh

It should be in order of O(log(row))+O(log(column)) rather O(log(column))*O(log(row)).
As time for searching for Correct row will take time in O(log(rows)) and searching for correct element in that row will take take time O(log(column)).

• pavansrinivas

actually it will be O(log(row*column)) which is nothing but(O(log(row)+log(column)))……this is justified because the above 2D matrix can be considered as a single sorted array with (row *column) elements and complexity of binary search in a sorted array with n elements is O(log(n)) ..

One Logic can be :

Start searching/comparing with Diagonal Elements of the matrix:
if(arr[i][i] == item)
{ //found the item }
if(arr[i][i] < item && arr[i+1][i+1] > item)
{ //find the element in rest of the ith row and rest of the ith column }
else
{
//increment “i” in loop
}

All above things can be done with binary search as well.
So,Time Complexity can be reduced to : O(log(m+n)).

• gaurav1424

Is there any way to do this in O(log n) ?

``` ```
/* Paste your code here (You may delete these lines if not writing code) */
``` ```
• rajat rastogi

Use Improved binary partition method given in leetcode.com

``` ```

``` ```
• rajat rastogi

In this case complexity will be
O(n) constant factor is very less.

• Shobhit

You can check the number with the middle element of matrix. Depending on whether it is smaller than the number we are searching or greater, we can eliminate 1/4th of the array(either top left part or bottom right part). So we are left with 3 smaller matrices of size 1/4th of the original matrix. Continue searching diagonals of these matrices and in the next step you will get 9 matrices of size 1/16 of the original. This approach will take time O(log(mn)) with log base as 4/3.

• Another Approach:

We can cut down the search space by examining the diagonal elements.

Trace the floor (ceil) value of x on the diagonal using binary search. The element ‘x’ must be in the row or column of floor (ceil) of x.

As an example x = 29 in the above matrix, and x floor value is 25 (ceil value is 37 at [2, 2]) whose indices are (1, 1), then search in the first row and first column (Again we can use binary search here).

There will be maximum of n elements on diagonal, and less than n elements in the reduced-matrices. Overall O(log n). The method works only on symmetric matrices.

Can we generalize the method for asymmetric matrices? Yes, I guess.

• Sorry, it can only bring down the search space. We can create counter example to above method.

• ddfd

This question was asked at Microsoft Internship interview 2011.

• ddfd

I think after we find that the last element in the row is greater than the required element then we can apply a binary search on that row . Hence Complexity would be O ( m + logn) if matrix of size m x n . For this case where m = n complexity would be O(n + logn) i.e O(n)

• @ddfd, the method fails as the 2D array is not strictly sorted. For example consider above case where x = 29, the end elements of first two rows are greater than 29, but they don’t contain required element.

If it is like apply binary search on every row, we end up with O(m log n) complexity.

• shanky

too gooood n simple solution man…..god knows what what type of algo i was trying

• can we tackle this problem like a binary search, only that at each point of time we will have 4 possibilities. we start at mat[(n-1)/2][(n-1)/2], now the number can be in any of the four quadrants.

``` ```

int midi = (n-1)/2, midj=(n-1)/2;
if(x == mat[midi][midj])
return true;
else if(x < mat[midi][midj-1] && x < mat[midi-1][midj])
p = midi-1, q = midj-1;
else if(x > mat[midi+1][midj] && x > mat[midi][midj+1])
p = midi+1, q = midj+1;
else if(x > mat[midi][midj-1] && x < mat[midi+1][midj])
p = midi+1, q = midj;
else if(x >mat[midi-1][midj] && x < mat[midi][midj+1])
p = midi-1, q = midj;
``` ```

please let me know if this should work.

• @shrikant: The approach should work, but the time complexity of this approach would be more than O(n). See the below comments from @Kartik and @Vamshi.

• shiv

superb

• Vamshi

One algorithm that i could come up with is as below.

1. Let A be the n*n array.
2. Report the element doesn’t exist in the array, if the search element e doesn’t satisfy the condition A[1,1] <= e <= A[n,n]
3. If n = 1, return true if the element in the array is same as search element.
3. Consider A[n,n] as a set of 4 subarrays of sizes n/2*n/2 and recursively search in them using the same algorithm.

At any given time, out of the four subarrays the recursive search will exit at the step 2 itself atleast for one array.
So, in the worst case, the complexity is like T(n) = 3T(n/4) + constant time which is strictly less than O(n^2).

Any thoughts?

• kartik

@Vamsi: The algo proposed by you is simple and good!

I think the time complexity should be T(n) = 3T(n/2) + C. The subproblems are of size n/2. It is still less than O(n^2) though.

• Vamshi

@kartik: I realised my mistake now.

The complexity of this algorithm will be now n^3/2. But the algorithm mentioned in the post is far better than this one as it is of linear time.

• Satyanarayana Batchu

I think time complexity is T(n) = 3 T(n/4) + C.

Then time complexity should be T(n) = n Pow log 3 base 4. i.e n Pow 0.602

This is far less than O(n), so this algorithm is better

• Kartik

No, it is n/2.

Original matrix size was n*n. The reduced matrix size is n/2*n/2

• reg_frenzy

Also, another optimization could be applied, extending the idea of girish. We could check if the element to be searched is lesser or greater than Matrix[n/2][n/2]. Depending on that we could make either the top right element or the bottom right element as the start element as the start element. This way, we effectively need to search only half the matrix.

This could also be extended recursively, searching half the arrays, every time.

• ynnus4u

another approach: given n x m matrix A[]][],find x, complexity O(log (min(m,n)))

Assume n < m, do binary search on 1st column & find the smallest element that is still larger than X.
Say it's gonna be A[i,0]. Now throw all rows after and including i (since X is smaller than all of these elements).
Repeat for a smaller matrix of size (i-1, m – 1) by proceeding to next column.

Proof of complexity : effectively we are searching along an array of size m, time complexity = O(log n)

• Given below are related posts,

http://geeksforgeeks.org/forum/topic/arrays-3

@Vick‘s method seems to be feasible (I haven’t tried). On big 2D arrays it may be worth considering.

I closed all of them to consolidate any further comments here.

Two conditions are missing and code can be optimized to handle those too:

``` ```
int search(int mat[4][4], int n, int x)
{
if(x <a> a[n][n]) return -1;  //Or return some exception code

int i = 0, j = n-1;  //set indexes for top right element
while ( i = 0 )
{
if ( mat[i][j] == x )
{
printf("\n Found at %d, %d", i, j);
return 1;
}
if ( mat[i][j] > x )
j--;
else //  if mat[i][j] < x
i++;
}