Open In App
Related Articles

Search in a Row-wise and Column-wise Sorted 2D Array using Divide and Conquer algorithm

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Report issue
Report

Given an n x n matrix, where every row and column is sorted in increasing order. Given a key, how to decide whether this key is in the matrix. 
A linear time complexity is discussed in the previous post. This problem can also be a very good example for divide and conquer algorithms. Following is divide and conquer algorithm.
1) Find the middle element. 
2) If middle element is same as key return. 
3) If middle element is lesser than key then 
….3a) search submatrix on lower side of middle element 
….3b) Search submatrix on right hand side.of middle element 
4) If middle element is greater than key then 
….4a) search vertical submatrix on left side of middle element 
….4b) search submatrix on right hand side.
 

DaCMat3


Following implementation of above algorithm. 
 

C++

// C++ program for implementation of
// divide and conquer algorithm
// to find a given key in a row-wise
// and column-wise sorted 2D array
#include<bits/stdc++.h>
#define ROW 4
#define COL 4
using namespace std;
 
// A divide and conquer method to
// search a given key in mat[]
// in rows from fromRow to toRow
// and columns from fromCol to
// toCol
void search(int mat[ROW][COL], int fromRow, int toRow,
                    int fromCol, int toCol, int key)
    {
        // Find middle and compare with middle
        int i = fromRow + (toRow-fromRow )/2;
        int j = fromCol + (toCol-fromCol )/2;
        if (mat[i][j] == key) // If key is present at middle
        cout<<"Found "<< key << " at "<< i <<
                            " " << j<<endl;
        else
        {
            // right-up quarter of matrix is searched in all cases.
            // Provided it is different from current call
            if (i != toRow || j != fromCol)
            search(mat, fromRow, i, j, toCol, key);
 
            // Special case for iteration with 1*2 matrix
            // mat[i][j] and mat[i][j+1] are only two elements.
            // So just check second element
            if (fromRow == toRow && fromCol + 1 == toCol)
            if (mat[fromRow][toCol] == key)
                cout<<"Found "<< key<< " at "<<
                            fromRow << " " << toCol<<endl;
 
            // If middle key is lesser then search lower horizontal
            // matrix and right hand side matrix
            if (mat[i][j] < key)
            {
                // search lower horizontal if such matrix exists
                if (i + 1 <= toRow)
                search(mat, i + 1, toRow, fromCol, toCol, key);
            }
 
            // If middle key is greater then search left vertical
            // matrix and right hand side matrix
            else
            {
                // search left vertical if such matrix exists
                if (j - 1 >= fromCol)
                search(mat, fromRow, toRow, fromCol, j - 1, key);
            }
        }
    }
 
// Driver code
int main()
{
    int mat[ROW][COL] = { {10, 20, 30, 40},
                            {15, 25, 35, 45},
                            {27, 29, 37, 48},
                            {32, 33, 39, 50}};
    int key = 50;
    for (int i = 0; i < ROW; i++)
    for (int j = 0; j < COL; j++)
        search(mat, 0, ROW - 1, 0, COL - 1, mat[i][j]);
    return 0;
}
 
// This code is contributed by Rajput-Ji

                    

Java

// Java program for implementation of divide and conquer algorithm
// to find a given key in a row-wise and column-wise sorted 2D array
class SearchInMatrix
{
    public static void main(String[] args)
    {
        int[][] mat = new int[][] { {10, 20, 30, 40},
                                    {15, 25, 35, 45},
                                    {27, 29, 37, 48},
                                    {32, 33, 39, 50}};
        int rowcount = 4,colCount=4,key=50;
        for (int i=0; i<rowcount; i++)
          for (int j=0; j<colCount; j++)
             search(mat, 0, rowcount-1, 0, colCount-1, mat[i][j]);
    }
 
    // A divide and conquer method to search a given key in mat[]
    // in rows from fromRow to toRow and columns from fromCol to
    // toCol
    public static void search(int[][] mat, int fromRow, int toRow,
                              int fromCol, int toCol, int key)
    {
        // Find middle and compare with middle
        int i = fromRow + (toRow-fromRow )/2;
        int j = fromCol + (toCol-fromCol )/2;
        if (mat[i][j] == key) // If key is present at middle
          System.out.println("Found "+ key + " at "+ i +
                               " " + j);
        else
        {
            // right-up quarter of matrix is searched in all cases.
            // Provided it is different from current call
            if (i!=toRow || j!=fromCol)
             search(mat,fromRow,i,j,toCol,key);
 
            // Special case for iteration with 1*2 matrix
            // mat[i][j] and mat[i][j+1] are only two elements.
            // So just check second element
            if (fromRow == toRow && fromCol + 1 == toCol)
              if (mat[fromRow][toCol] == key)
                System.out.println("Found "+ key+ " at "+
                                   fromRow + " " + toCol);
 
            // If middle key is lesser then search lower horizontal
            // matrix and right hand side matrix
            if (mat[i][j] < key)
            {
                // search lower horizontal if such matrix exists
                if (i+1<=toRow)
                  search(mat, i+1, toRow, fromCol, toCol, key);
            }
 
            // If middle key is greater then search left vertical
            // matrix and right hand side matrix
            else
            {
                // search left vertical if such matrix exists
                if (j-1>=fromCol)
                  search(mat, fromRow, toRow, fromCol, j-1, key);
            }
        }
    }
}

                    

Python3

# Python3 program for implementation of
# divide and conquer algorithm to find
# a given key in a row-wise and column-wise
# sorted 2D array a divide and conquer method
# to search a given key in mat in rows from
# fromRow to toRow and columns from fromCol to
# toCol
def search(mat, fromRow, toRow, fromCol, toCol, key):
 
    # Find middle and compare with middle
    i = fromRow + (toRow - fromRow) // 2;
    j = fromCol + (toCol - fromCol) // 2;
    if (mat[i][j] == key): # If key is present at middle
        print("Found " , key , " at " , i , " " , j);
    else:
 
        # right-up quarter of matrix is searched in all cases.
        # Provided it is different from current call
        if (i != toRow or j != fromCol):
            search(mat, fromRow, i, j, toCol, key);
 
        # Special case for iteration with 1*2 matrix
        # mat[i][j] and mat[i][j+1] are only two elements.
        # So just check second element
        if (fromRow == toRow and fromCol + 1 == toCol):
            if (mat[fromRow][toCol] == key):
                print("Found " , key , " at " , fromRow , " " , toCol);
 
        # If middle key is lesser then search lower horizontal
        # matrix and right hand side matrix
        if (mat[i][j] < key):
 
            # search lower horizontal if such matrix exists
            if (i + 1 <= toRow):
                search(mat, i + 1, toRow, fromCol, toCol, key);
 
        # If middle key is greater then search left vertical
        # matrix and right hand side matrix
        else:
             
            # search left vertical if such matrix exists
            if (j - 1 >= fromCol):
                search(mat, fromRow, toRow, fromCol, j - 1, key);
 
# Driver code
if __name__ == '__main__':
    mat = [[ 10, 20, 30, 40],
           [15, 25, 35, 45],
           [27, 29, 37, 48],
           [32, 33, 39, 50]];
    rowcount = 4; colCount = 4; key = 50;
    for i in range(rowcount):
        for j in range(colCount):
            search(mat, 0, rowcount - 1, 0, colCount - 1, mat[i][j]);
 
# This code is contributed by 29AjayKumar

                    

C#

// C# program for implementation of
// divide and conquer algorithm
// to find a given key in a row-wise
// and column-wise sorted 2D array
using System;
 
public class SearchInMatrix
{
    public static void Main(String[] args)
    {
        int[,] mat = new int[,] { {10, 20, 30, 40},
                                    {15, 25, 35, 45},
                                    {27, 29, 37, 48},
                                    {32, 33, 39, 50}};
        int rowcount = 4, colCount = 4, key = 50;
        for (int i = 0; i < rowcount; i++)
            for (int j = 0; j < colCount; j++)
            search(mat, 0, rowcount - 1, 0, colCount - 1, mat[i, j]);
    }
 
    // A divide and conquer method to
    // search a given key in mat[]
    // in rows from fromRow to toRow
    // and columns from fromCol to
    // toCol
    public static void search(int[,] mat, int fromRow, int toRow,
                            int fromCol, int toCol, int key)
    {
        // Find middle and compare with middle
        int i = fromRow + (toRow-fromRow )/2;
        int j = fromCol + (toCol-fromCol )/2;
        if (mat[i, j] == key) // If key is present at middle
        Console.WriteLine("Found "+ key + " at "+ i +
                            " " + j);
        else
        {
            // right-up quarter of matrix is searched in all cases.
            // Provided it is different from current call
            if (i != toRow || j != fromCol)
            search(mat, fromRow, i, j, toCol, key);
 
            // Special case for iteration with 1*2 matrix
            // mat[i][j] and mat[i][j+1] are only two elements.
            // So just check second element
            if (fromRow == toRow && fromCol + 1 == toCol)
            if (mat[fromRow,toCol] == key)
                Console.WriteLine("Found "+ key + " at "+
                                fromRow + " " + toCol);
 
            // If middle key is lesser then search lower horizontal
            // matrix and right hand side matrix
            if (mat[i, j] < key)
            {
                // search lower horizontal if such matrix exists
                if (i + 1 <= toRow)
                search(mat, i + 1, toRow, fromCol, toCol, key);
            }
 
            // If middle key is greater then search left vertical
            // matrix and right hand side matrix
            else
            {
                // search left vertical if such matrix exists
                if (j - 1 >= fromCol)
                search(mat, fromRow, toRow, fromCol, j - 1, key);
            }
        }
    }
}
 
// This code has been contributed by 29AjayKumar

                    

Javascript

<script>
 
// JavaScript program for implementation
// of divide and conquer algorithm
// to find a given key in a row-wise
// and column-wise sorted 2D array
     
 
    // A divide and conquer method to search a given key in mat
    // in rows from fromRow to toRow and columns from fromCol to
    // toCol
    function search(mat , fromRow , toRow,
                               fromCol , toCol , key)
    {
        // Find middle and compare with middle
        var i = parseInt(fromRow + (toRow-fromRow )/2);
        var j = parseInt(fromCol + (toCol-fromCol )/2);
        if (mat[i][j] == key) // If key is present at middle
          document.write("Found "+ key + " at "+ i +
                               " " + j+"<br/>");
        else
        {
            // right-up quarter of matrix is searched in all cases.
            // Provided it is different from current call
            if (i!=toRow || j!=fromCol)
             search(mat,fromRow,i,j,toCol,key);
 
            // Special case for iteration with 1*2 matrix
            // mat[i][j] and mat[i][j+1] are only two elements.
            // So just check second element
            if (fromRow == toRow && fromCol + 1 == toCol)
              if (mat[fromRow][toCol] == key)
                document.write("Found "+ key+ " at "+
                                   fromRow + " " + toCol+"<br/>");
 
            // If middle key is lesser then search lower horizontal
            // matrix and right hand side matrix
            if (mat[i][j] < key)
            {
                // search lower horizontal if such matrix exists
                if (i+1<=toRow)
                  search(mat, i+1, toRow, fromCol, toCol, key);
            }
 
            // If middle key is greater then search left vertical
            // matrix and right hand side matrix
            else
            {
                // search left vertical if such matrix exists
                if (j-1>=fromCol)
                  search(mat, fromRow, toRow, fromCol, j-1, key);
            }
        }
        }
 
       var mat = [[10, 20, 30, 40],
                   [15, 25, 35, 45],
                   [27, 29, 37, 48],
                   [32, 33, 39, 50]];
        var rowcount = 4,colCount=4,key=50;
        for (var i=0; i<rowcount; i++)
          for (var j=0; j<colCount; j++)
             search(mat, 0, rowcount-1, 0, colCount-1, mat[i][j]);
              
// This code contributed by umadevi9616
 
</script>

                    

Output
Found 10 at 0 0
Found 20 at 0 1
Found 30 at 0 2
Found 40 at 0 3
Found 15 at 1 0
Found 25 at 1 1
Found 35 at 1 2
Found 45 at 1 3
Found 27 at 2 0
Found 29 at 2 1
Found 37 at 2 2
Found 48 at 2 3
Found 32 at 3 0
Found 33 at 3 1
Found 39 at 3 2
Found 50 at 3 3


Time complexity: 
We are given a n*n matrix, the algorithm can be seen as recurring for 3 matrices of size n/2 x n/2. Following is recurrence for time complexity 

 T(n) = 3T(n/2) + O(1) 

Space Complexity: O(log(n))

The solution of recurrence is O(n1.58) using Master Method. 
But the actual implementation calls for one submatrix of size n x n/2 or n/2 x n, and other submatrix of size n/2 x n/2.

Approach :

The approach below  is a modified version of the binary search algorithm, called Binary Search on Rows algorithm.

  1. Loop through each row of the matrix.
  2. Check if the key falls within the range of the current row (i.e., if the first element of the row is less than or equal to the key and the last element of the row is greater than or equal to the key).
  3. If the key falls within the range of the current row, perform binary search on that row to find the key.
  4. If the key is found, print the row and column index of the key and return.
  5. If the key is not found in any row, print that the key was not found.

implementation of above approach 

C++

#include <bits/stdc++.h>
#define ROW 4
#define COL 4
using namespace std;
 
bool binary_search(int mat[ROW][COL], int row, int start,
                   int end, int key)
{
    while (start <= end) {
        int mid = start + (end - start) / 2;
        if (mat[row][mid] == key) {
            return true;
        }
        else if (mat[row][mid] < key) {
            start = mid + 1;
        }
        else {
            end = mid - 1;
        }
    }
    return false;
}
 
void search(int mat[ROW][COL], int key)
{
    // search in each row
    for (int i = 0; i < ROW; i++) {
        // perform binary search in current row
        if (mat[i][0] <= key && mat[i][COL - 1] >= key) {
            if (binary_search(mat, i, 0, COL - 1, key)) {
                cout << "Found " << key << " at " << i
                     << " " << endl;
                return;
            }
        }
    }
    cout << key << " not found" << endl;
}
 
// Driver code
int main()
{
    int mat[ROW][COL] = { { 10, 20, 30, 40 },
                          { 15, 25, 35, 45 },
                          { 27, 29, 37, 48 },
                          { 32, 33, 39, 50 } };
    int key = 50;
    search(mat, key);
    return 0;
}

                    

Java

import java.util.*;
 
class Main {
    static final int ROW = 4;
    static final int COL = 4;
    static boolean binarySearch(int[][] mat, int row,
                                int start, int end, int key)
    {
        while (start <= end) {
            int mid = start + (end - start) / 2;
            if (mat[row][mid] == key) {
                return true;
            }
            else if (mat[row][mid] < key) {
                start = mid + 1;
            }
            else {
                end = mid - 1;
            }
        }
        return false;
    }
 
    static void search(int[][] mat, int key)
    {
        // search in each row
        for (int i = 0; i < ROW; i++) {
            // perform binary search in current row
            if (mat[i][0] <= key
                && mat[i][COL - 1] >= key) {
                if (binarySearch(mat, i, 0, COL - 1, key)) {
                    System.out.println("Found " + key
                                       + " at " + i);
                    return;
                }
            }
        }
        System.out.println(key + " not found");
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int[][] mat = { { 10, 20, 30, 40 },
                        { 15, 25, 35, 45 },
                        { 27, 29, 37, 48 },
                        { 32, 33, 39, 50 } };
        int key = 50;
        search(mat, key);
    }
}

                    

Python3

row = 4
col = 4
 
# Function to perform binary search on a row of the matrix
def binary_search(mat, row, start, end, key):
    while start <= end:
        mid = start + (end - start)
 
        if mat[row][mid] == key:
            return True
        elif mat[row][mid] < key:
            start = mid + 1
        else:
            end = mid - 1
 
    return False
 
 
# Function to search for a given key in the matrix
def search(mat, key):
   
    # Search in each row
    for i in range(row):
       
      # Perform binary search in current row
        if mat[i][0] <= key <= mat[i][col-1]:
            if binary_search(mat, i, 0, col-1, key):
                print(f"Found {key} at {i}")
                return True
    print(f"{key} not found")
    return False
 
# Test the code with an example matrix and value of key
mat = [[10, 20, 30, 40],
       [15, 25, 35, 45],
       [27, 29, 37, 48],
       [32, 33, 39, 50]]
key = 50
search(mat, key)

                    

C#

using System;
 
class Program
{
  const int ROW = 4;
  const int COL = 4;
 
  static bool BinarySearch(int[,] mat, int row, int start, int end, int key)
  {
    while (start <= end)
    {
      int mid = start + (end - start) / 2;
      if (mat[row, mid] == key)
      {
        return true;
      }
      else if (mat[row, mid] < key)
      {
        start = mid + 1;
      }
      else
      {
        end = mid - 1;
      }
    }
    return false;
  }
 
  static void Search(int[,] mat, int key)
  {
    // search in each row
    for (int i = 0; i < ROW; i++)
    {
      // perform binary search in current row
      if (mat[i, 0] <= key && mat[i, COL - 1] >= key)
      {
        if (BinarySearch(mat, i, 0, COL - 1, key))
        {
          Console.WriteLine("Found " + key + " at " + i);
          return;
        }
      }
    }
    Console.WriteLine(key + " not found");
  }
 
  // Driver code
  static void Main()
  {
    int[,] mat = { { 10, 20, 30, 40 },
                  { 15, 25, 35, 45 },
                  { 27, 29, 37, 48 },
                  { 32, 33, 39, 50 } };
    int key = 50;
    Search(mat, key);
  }
}
 
// This code is contributed by Prajwal Kandekar

                    

Javascript

const ROW = 4;
const COL = 4;
 
// Function to perform binary search on a row of the matrix
function binary_search(mat, row, start, end, key) {
    while (start <= end) {
        let mid = start + Math.floor((end - start) / 2);
        if (mat[row][mid] == key) {
            return true;
        } else if (mat[row][mid] < key) {
            start = mid + 1;
        } else {
            end = mid - 1;
        }
    }
    return false;
}
 
// Function to search for a given key in the matrix
function search(mat, key) {
    // Search in each row
    for (let i = 0; i < ROW; i++) {
        // Perform binary search in current row
        if (mat[i][0] <= key && mat[i][COL-1] >= key) {
            if (binary_search(mat, i, 0, COL-1, key)) {
                console.log("Found " + key + " at " + i);
                return;
            }
        }
    }
    console.log(key + " not found");
}
 
// Test the code with an example matrix and value of key
let mat = [ [10, 20, 30, 40],
            [15, 25, 35, 45],
            [27, 29, 37, 48],
            [32, 33, 39, 50]];
    let key = 50;
    search(mat, key);

                    

Output
Found 50 at 3 

Time complexity analysis:

In the worst case, we will perform binary search on each of the ROW rows of the matrix. The time complexity of binary search is O(log COL), and we perform it ROW times, so the overall time complexity of the Binary Search on Rows algorithm is O(ROW * log COL). Since the matrix is row-wise and column-wise sorted, we can assume that ROW and COL are roughly the same size, so the time complexity can be simplified to O(N log N), where N = ROW = COL.

Space Complexity Analysis: O(1), we only use a constant amount of extra space to store some variables and constants.



 



Last Updated : 13 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads