Find median in row wise sorted matrix
We are given a row-wise sorted matrix of size r*c, we need to find the median of the matrix given. It is assumed that r*c is always odd.
Examples:
Input: 1 3 5 2 6 9 3 6 9 Output: Median is 5 If we put all the values in a sorted array A[] = 1 2 3 3 5 6 6 9 9) Input: 1 3 4 2 5 6 7 8 9 Output: Median is 5
Simple Method: The simplest method to solve this problem is to store all the elements of the given matrix in an array of size r*c. Then we can either sort the array and find the median element in O(r*clog(r*c)) ,
C++
#include <iostream> #include <vector> #include <algorithm> using namespace std; double find_median(vector<vector< int >> matrix) { // Flatten the matrix into a 1D array vector< int > arr; for ( int i = 0; i < matrix.size(); i++) { for ( int j = 0; j < matrix[0].size(); j++) { arr.push_back(matrix[i][j]); } } // Sort the array sort(arr.begin(), arr.end()); // Find the median element int mid = arr.size() / 2; double median; if (arr.size() % 2 == 0) { median = (arr[mid-1] + arr[mid]) / 2.0; } else { median = arr[mid]; } return median; } int main() { // Example 1 vector<vector< int >> matrix1 = {{1, 3, 5}, {2, 6, 9}, {3, 6, 9}}; double median1 = find_median(matrix1); cout << "Median of matrix1: " << median1 << endl; // Example 2 vector<vector< int >> matrix2 = {{1, 3, 4}, {2, 5, 6}, {7, 8, 9}}; double median2 = find_median(matrix2); cout << "Median of matrix2: " << median2 << endl; return 0; } |
Java
import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Main { public static double findMedian(List<List<Integer>> matrix) { // Flatten the matrix into a 1D list List<Integer> list = new ArrayList<Integer>(); for ( int i = 0 ; i < matrix.size(); i++) { for ( int j = 0 ; j < matrix.get( 0 ).size(); j++) { list.add(matrix.get(i).get(j)); } } // Sort the list Collections.sort(list); // Find the median element int mid = list.size() / 2 ; double median; if (list.size() % 2 == 0 ) { median = (list.get(mid - 1 ) + list.get(mid)) / 2.0 ; } else { median = list.get(mid); } return median; } public static void main(String[] args) { // Example 1 List<List<Integer>> matrix1 = new ArrayList<List<Integer>>(); matrix1.add( new ArrayList<Integer>(){{add( 1 ); add( 3 ); add( 5 );}}); matrix1.add( new ArrayList<Integer>(){{add( 2 ); add( 6 ); add( 9 );}}); matrix1.add( new ArrayList<Integer>(){{add( 3 ); add( 6 ); add( 9 );}}); double median1 = findMedian(matrix1); System.out.println( "Median of matrix1: " + median1); // Example 2 List<List<Integer>> matrix2 = new ArrayList<List<Integer>>(); matrix2.add( new ArrayList<Integer>(){{add( 1 ); add( 3 ); add( 4 );}}); matrix2.add( new ArrayList<Integer>(){{add( 2 ); add( 5 ); add( 6 );}}); matrix2.add( new ArrayList<Integer>(){{add( 7 ); add( 8 ); add( 9 );}}); double median2 = findMedian(matrix2); System.out.println( "Median of matrix2: " + median2); } } |
Python
def find_median(matrix): # Flatten the matrix into a 1D array arr = [] for i in range ( len (matrix)): for j in range ( len (matrix[ 0 ])): arr.append(matrix[i][j]) # Sort the array arr.sort() # Find the median element mid = len (arr) / / 2 if len (arr) % 2 = = 0 : median = (arr[mid - 1 ] + arr[mid]) / 2 else : median = arr[mid] return median # Example 1 matrix1 = [[ 1 , 3 , 5 ], [ 2 , 6 , 9 ], [ 3 , 6 , 9 ]] median1 = find_median(matrix1) print ( "Median of matrix1:" , median1) # Example 2 matrix2 = [[ 1 , 3 , 4 ], [ 2 , 5 , 6 ], [ 7 , 8 , 9 ]] median2 = find_median(matrix2) print ( "Median of matrix2:" , median2) |
('Median of matrix1:', 5) ('Median of matrix2:', 5)
Another Approach we can use the approach discussed here to find the median in O(r*c). Auxiliary space required will be O(r*c) in both cases.
An efficient approach for this problem is to use a binary search algorithm. The idea is that for a number to be median there should be exactly (n/2) numbers that are less than this number. So, we try to find the count of numbers less than all the numbers. Below is the step-by-step algorithm for this approach:
Algorithm:
- First, we find the minimum and maximum elements in the matrix. The minimum element can be easily found by comparing the first element of each row, and similarly, the maximum element can be found by comparing the last element of each row.
- Then we use binary search on our range of numbers from minimum to maximum, we find the mid of the min and max and get a count of numbers less than or equal to our mid. And accordingly change the min or max.
- For a number to be median, there should be (r*c)/2 numbers smaller than that number. So for every number, we get the count of numbers less than or equal to that by using upper_bound() in each row of the matrix, if it is less than the required count, the median must be greater than the selected number, else the median must be less than or equal to the selected number.
Below is the implementation of the above approach:
C++
// C++ program to find median of a matrix // sorted row wise #include<bits/stdc++.h> using namespace std; const int MAX = 100; // function to find median in the matrix int binaryMedian( int m[][MAX], int r , int c) { int min = INT_MAX, max = INT_MIN; for ( int i=0; i<r; i++) { // Finding the minimum element if (m[i][0] < min) min = m[i][0]; // Finding the maximum element if (m[i][c-1] > max) max = m[i][c-1]; } int desired = (r * c + 1) / 2; while (min < max) { int mid = min + (max - min) / 2; int place = 0; // Find count of elements smaller than or equal to mid for ( int i = 0; i < r; ++i) place += upper_bound(m[i], m[i]+c, mid) - m[i]; if (place < desired) min = mid + 1; else max = mid; } return min; } // driver program to check above functions int main() { int r = 3, c = 3; int m[][MAX]= { {1,3,5}, {2,6,9}, {3,6,9} }; cout << "Median is " << binaryMedian(m, r, c) << endl; return 0; } |
Java
// Java program to find median of a matrix // sorted row wise import java.util.Arrays; public class MedianInRowSorted { // function to find median in the matrix static int binaryMedian( int m[][], int r, int c) { int max = Integer.MIN_VALUE; int min = Integer.MAX_VALUE; for ( int i = 0 ; i < r; i++) { // Finding the minimum element if (m[i][ 0 ] < min) min = m[i][ 0 ]; // Finding the maximum element if (m[i] > max) max = m[i]; } int desired = (r * c + 1 ) / 2 ; while (min < max) { int mid = min + (max - min) / 2 ; int place = 0 ; int get = 0 ; // Find count of elements smaller than or equal // to mid for ( int i = 0 ; i < r; ++i) { get = Arrays.binarySearch(m[i], mid); // If element is not found in the array the // binarySearch() method returns // (-(insertion_point) - 1). So once we know // the insertion point we can find elements // Smaller than the searched element by the // following calculation if (get < 0 ) get = Math.abs(get) - 1 ; // If element is found in the array it // returns the index(any index in case of // duplicate). So we go to last index of // element which will give the number of // elements smaller than the number // including the searched element. else { while (get < m[i].length && m[i][get] == mid) get += 1 ; } place = place + get; } if (place < desired) min = mid + 1 ; else max = mid; } return min; } // Driver Program to test above method. public static void main(String[] args) { int r = 3 , c = 3 ; int m[][] = { { 1 , 3 , 5 }, { 2 , 6 , 9 }, { 3 , 6 , 9 } }; System.out.println( "Median is " + binaryMedian(m, r, c)); } } // This code is contributed by Sumit Ghosh |
Python3
# Python program to find median of matrix # sorted row wise from bisect import bisect_right as upper_bound MAX = 100 ; # Function to find median in the matrix def binaryMedian(m, r, d): mi = m[ 0 ][ 0 ] mx = 0 for i in range (r): if m[i][ 0 ] < mi: mi = m[i][ 0 ] if m[i][d - 1 ] > mx : mx = m[i][d - 1 ] desired = (r * d + 1 ) / / 2 while (mi < mx): mid = mi + (mx - mi) / / 2 place = [ 0 ]; # Find count of elements smaller than or equal to mid for i in range (r): j = upper_bound(m[i], mid) place[ 0 ] = place[ 0 ] + j if place[ 0 ] < desired: mi = mid + 1 else : mx = mid print ( "Median is" , mi) return # Driver code r, d = 3 , 3 m = [ [ 1 , 3 , 5 ], [ 2 , 6 , 9 ], [ 3 , 6 , 9 ]] binaryMedian(m, r, d) # This code is contributed by Sachin BIsht |
C#
// C# program to find median // of a matrix sorted row wise using System; class MedianInRowSorted{ // Function to find median // in the matrix static int binaryMedian( int [,]m, int r, int c) { int max = int .MinValue; int min = int .MaxValue; for ( int i = 0; i < r; i++) { // Finding the minimum // element if (m[i, 0] < min) min = m[i, 0]; // Finding the maximum // element if (m[i, c - 1] > max) max = m[i, c - 1]; } int desired = (r * c + 1) / 2; while (min < max) { int mid = min + (max - min) / 2; int place = 0; int get = 0; // Find count of elements // smaller than or equal to mid for ( int i = 0; i < r; ++i) { get = Array.BinarySearch( GetRow(m, i), mid); // If element is not found // in the array the binarySearch() // method returns (-(insertion_ // point) - 1). So once we know // the insertion point we can // find elements Smaller than // the searched element by the // following calculation if ( get < 0) get = Math.Abs( get ) - 1; // If element is found in the // array it returns the index(any // index in case of duplicate). So // we go to last index of element // which will give the number of // elements smaller than the number // including the searched element. else { while ( get < GetRow(m, i).GetLength(0) && m[i, get ] == mid) get += 1; } place = place + get ; } if (place < desired) min = mid + 1; else max = mid; } return min; } public static int [] GetRow( int [,] matrix, int row) { var rowLength = matrix.GetLength(1); var rowVector = new int [rowLength]; for ( var i = 0; i < rowLength; i++) rowVector[i] = matrix[row, i]; return rowVector; } // Driver code public static void Main(String[] args) { int r = 3, c = 3; int [,]m = {{1,3,5}, {2,6,9}, {3,6,9} }; Console.WriteLine( "Median is " + binaryMedian(m, r, c)); } } // This code is contributed by Princi Singh |
Javascript
<script> // Javascript program to find median // of a matrix sorted row wise // Function to find median // in the matrix function binaryMedian(m, r, c) { var max = -1000000000; var min = 1000000000; for ( var i = 0; i < r; i++) { // Finding the minimum // element if (m[i][0] < min) min = m[i][0]; // Finding the maximum // element if (m[i] > max) max = m[i]; } var desired = parseInt((r * c + 1) / 2); while (min < max) { var mid = min + parseInt((max - min) / 2); var place = 0; var get = 0; // Find count of elements // smaller than or equal to mid for ( var i = 0; i < r; ++i) { var tmp = GetRow(m, i); for ( var j = tmp.length; j>=0; j--) { if (tmp[j] <= mid) { get = j+1; break ; } } // If element is not found // in the array the binarySearch() // method returns (-(insertion_ // point) - 1). So once we know // the insertion point we can // find elements Smaller than // the searched element by the // following calculation if (get < 0) get = Math.abs(get) - 1; // If element is found in the // array it returns the index(any // index in case of duplicate). So // we go to last index of element // which will give the number of // elements smaller than the number // including the searched element. else { while (get < GetRow(m, i).length && m[i][get] == mid) get += 1; } place = place + get; } if (place < desired) min = mid + 1; else max = mid; } return min; } function GetRow(matrix, row) { var rowLength = matrix[0].length; var rowVector = Array(rowLength).fill(0); for ( var i = 0; i < rowLength; i++) rowVector[i] = matrix[row][i]; return rowVector; } // Driver code var r = 3, c = 3; var m = [[1,3,5], [2,6,9], [3,6,9]]; document.write( "Median is " + binaryMedian(m, r, c)); // This code is contributed by rutvik_56. </script> |
Median is 5
Time Complexity: O(32 * r * log(c)). The upper bound function will take log(c) time and is performed for each row. And since the numbers will be max of 32 bit, so binary search of numbers from min to max will be performed in at most 32 ( log2(2^32) = 32 ) operations.
Auxiliary Space: O(1)
Method 2 – Using a min heap – Priority Queue
When we need to find the nth smallest element in a row or a column sorted matrix, we can use a min heap and a class node{val,row,col},
Since the matrix is row sorted the smallest element will be one among the first elements of all row ,
so push all first element of rows in the min heap, then for top element in heap push the second column element in that row ,if it is smallest it will be on top, or the other smallest element will be on top.
Repeat this process of popping the top elements till (r*c)/2.
In this problem this concept is used to find the median of the row sorted matrix.
C++
#include<bits/stdc++.h> using namespace std; class node{ public : int data; int row; int col; node( int d, int r, int c){ row = r; col = c; data = d; } }; class compare{ public : bool operator()(node* a, node* b){ return a->data > b->data; } }; class Solution{ public : int median(vector<vector< int >> &matrix, int R, int C){ priority_queue<node*, vector<node*>, compare>minheap; int count = 0, median = -1; int medianindex = (R*C)/2; for ( int i = 0; i<R; i++){ node* temp = new node(matrix[i][0], i, 0); minheap.push(temp); } while (count <= medianindex){ node* top = minheap.top(); minheap.pop(); int row = top->row; int col = top->col; median = top->data; count++; if (col+1 < C){ col++; node* temp = new node(matrix[row][col], row, col); minheap.push(temp); } } return median; } }; int main() { int r=3; int c=3; vector<vector< int >> matrix={{1, 3, 5}, {2, 6, 9}, {3, 6, 9}}; Solution obj; cout<<obj.median(matrix, r, c)<<endl; return 0; } |
Java
// Node class contains 3 fields - data, row, and col. // It initializes the values of these fields in its // constructor. import java.util.*; class Node { int data; // contains the value of the current node int row; // contains the row number of the current node // in the matrix int col; // contains the column number of the current // node in the matrix Node( int d, int r, int c) { row = r; col = c; data = d; } } // Compare class implements the Comparator interface and // overrides the compare method. It is used to compare 2 // nodes and determine the order in which they should be // inserted in the min heap. class Compare implements Comparator<Node> { public int compare(Node a, Node b) { // if a.data is greater than b.data, return 1 // else return -1 return a.data > b.data ? 1 : - 1 ; } } // Solution class contains the main logic to find median class Solution { public int median( int [][] matrix, int R, int C) { // minheap is a priority queue implemented using min // heap data structure. It stores the nodes in // ascending order based on their values. PriorityQueue<Node> minheap = new PriorityQueue<>( new Compare()); int count = 0 , median = - 1 ; // count variable to keep track of the // number of nodes processed so far // median variable to store the median value in the // end medianindex is the index of the median in the // matrix int medianindex = (R * C) / 2 ; // Push the first elements of each row in the min // heap for ( int i = 0 ; i < R; i++) { Node temp = new Node(matrix[i][ 0 ], i, 0 ); minheap.add(temp); } // Repeat until we reach the medianindex while (count <= medianindex) { Node top = minheap.poll(); // remove the node with // the smallest value from // the min heap int row = top.row; int col = top.col; median = top.data; count++; // if the current node is not the last element // in its row, push the next element from the // same row into the min heap if (col + 1 < C) { col++; Node temp = new Node(matrix[row][col], row, col); minheap.add(temp); } } return median; } } // Main class contains the main method public class Main { public static void main(String[] args) { int r = 3 ; // number of rows in the matrix int c = 3 ; // number of columns in the matrix int [][] matrix = { { 1 , 3 , 5 }, { 2 , 6 , 9 }, { 3 , 6 , 9 } }; Solution obj = new Solution(); // Call the median method from the Solution class // and print the result System.out.println(obj.median(matrix, r, c)); } } //This Code is Contributed by chinmaya121221 |
Python3
# import library for min heap import heapq from typing import List # Node class # contains the value of the current node # contains the row number of the current node # in the matrix # contains the column number of the current # node in the matrix class Node: def __init__( self , data: int , row: int , col: int ): self .data = data self .row = row self .col = col def __lt__( self , other): return self .data < other.data # Solution class contains the main logic to find median class Solution: # median function def median( self , matrix, R, C): # minheap is a priority queue implemented using min # heap data structure. It stores the nodes in # ascending order based on their values. minheap = [] # count variable to keep track of the # number of nodes processed so far count = 0 # median variable to store the median value in the # end medianindex is the index of the median in the # matrix median = - 1 medianindex = (R * C) / / 2 # Push the first elements of each row in the min # heap for i in range (R): temp = Node(matrix[i][ 0 ], i, 0 ) heapq.heappush(minheap, temp) # Repeat until we reach the medianindex while count < = medianindex: top = heapq.heappop(minheap) # remove the node with # the smallest value from # the min heap row = top.row col = top.col median = top.data count + = 1 # if the current node is not the last element # in its row, push the next element from the # same row into the min heap if col + 1 < C: col + = 1 temp = Node(matrix[row][col], row, col) heapq.heappush(minheap, temp) return median # Main class contains the main method if __name__ = = "__main__" : r = 3 c = 3 matrix = [[ 1 , 3 , 5 ], [ 2 , 6 , 9 ], [ 3 , 6 , 9 ]] obj = Solution() print (obj.median(matrix, r, c)) |
C#
//c# code for the above approach using System; using System.Collections.Generic; public class Node { public int Data { get ; set ; } // contains the value of the current node public int Row { get ; set ; } // contains the row number of the current node // in the matrix public int Col { get ; set ; } // contains the column number of the current // node in the matrix public Node( int data, int row, int col) { Data = data; Row = row; Col = col; } } public class Solution { public int Median(List<List< int >> matrix, int R, int C) { var minHeap = new PriorityQueue<Node>((a, b) => a.Data.CompareTo(b.Data)); // minheap is a priority queue implemented using min // heap data structure. It stores the nodes in // ascending order based on their values. int count = 0, median = -1; // count variable to keep track of the // number of nodes processed so far // median variable to store the median value in the // end medianindex is the index of the median in the // matrix int medianIndex = (R * C) / 2; // Push the first elements of each row in the min // heap for ( int i = 0; i < R; i++) { var temp = new Node(matrix[i][0], i, 0); minHeap.Enqueue(temp); } // Repeat until we reach the medianindex while (count <= medianIndex) { var top = minHeap.Dequeue(); // remove the node with // the smallest value from // the min heap int row = top.Row; int col = top.Col; median = top.Data; count++; // if the current node is not the last element // in its row, push the next element from the // same row into the min heap if (col + 1 < C) { col++; var temp = new Node(matrix[row][col], row, col); minHeap.Enqueue(temp); } } return median; } } public class PriorityQueue<T> { private List<T> heap; private Comparison<T> comparison; // Compare class implements the Comparator interface and // overrides the compare method. It is used to compare 2 // nodes and determine the order in which they should be // inserted in the min heap. public PriorityQueue(Comparison<T> comparison) { heap = new List<T>(); this .comparison = comparison; } public int Count { get { return heap.Count; } } // custom class to implement the enqueue function in priority //queue public void Enqueue(T item) { heap.Add(item); int i = heap.Count - 1; while (i > 0) { int parent = (i - 1) / 2; if (comparison(heap[parent], item) <= 0) { break ; } heap[i] = heap[parent]; i = parent; } heap[i] = item; } // custom class to implement the dequeue function in priority //queue public T Dequeue() { T item = heap[0]; int lastIndex = heap.Count - 1; heap[0] = heap[lastIndex]; heap.RemoveAt(lastIndex); lastIndex--; int i = 0; while ( true ) { int leftChild = 2 * i + 1; int rightChild = 2 * i + 2; if (leftChild > lastIndex) { break ; } int minChild = leftChild; if (rightChild <= lastIndex && comparison(heap[rightChild], heap[leftChild]) < 0) { minChild = rightChild; } if (comparison(heap[i], heap[minChild]) <= 0) { break ; } T temp = heap[i]; heap[i] = heap[minChild]; heap[minChild] = temp; i = minChild; } return item; } public T Peek() { return heap[0]; } } public class GFG { public static void Main() { int R = 3; int C = 3; var matrix = new List<List< int >> { new List< int > {1, 3, 5}, new List< int > {2, 6, 9}, new List< int > {3, 6, 9} }; var obj = new Solution(); Console.WriteLine(obj.Median(matrix, R, C)); } } |
Javascript
class Node { constructor(data, row, col) { this .data = data; // data to be stored in the node this .row = row; // row index of the data in the matrix this .col = col; // column index of the data in the matrix } } class MinHeap { constructor(compareFunc) { this .heap = []; // array to store the heap this .compare = compareFunc; // comparison function to determine the priority of nodes } push(node) { this .heap.push(node); // add the node to the end of the heap let current = this .heap.length - 1; // bubble up the node until the heap property is satisfied while (current > 0) { let parent = Math.floor((current - 1) / 2); // index of the parent node if ( this .compare( this .heap[current], this .heap[parent])) { // if the child node has higher priority than its parent node let temp = this .heap[current]; this .heap[current] = this .heap[parent]; // swap the child node with its parent node this .heap[parent] = temp; current = parent; // update the index of the child node to be its parent node } else { break ; // stop bubbling up if the child node has lower priority than its parent node } } } pop() { if ( this .heap.length === 0) return null ; // if the heap is empty, return null let result = this .heap[0]; // retrieve the root node this .heap[0] = this .heap.pop(); // move the last node to the root position let current = 0; // bubble down the root node until the heap property is satisfied while ( true ) { let left = 2 * current + 1; // index of the left child node let right = 2 * current + 2; // index of the right child node let smallest = current; // find the node with highest priority among the root node and its children if ( left < this .heap.length && this .compare( this .heap[left], this .heap[smallest]) ) { smallest = left; } if ( right < this .heap.length && this .compare( this .heap[right], this .heap[smallest]) ) { smallest = right; } if (smallest === current) { break ; // stop bubbling down if the root node has higher priority than its children } else { let temp = this .heap[current]; this .heap[current] = this .heap[smallest]; // swap the root node with its child node that has higher priority this .heap[smallest] = temp; current = smallest; // update the index of the root node to be its child node } } return result; // return the popped node } size() { return this .heap.length; // return the size of the heap } peek() { return this .heap.length > 0 ? this .heap[0] : null ; // return the root node if the heap is not empty, otherwise return null } } class Solution { median(matrix, R, C) { let minHeap = new MinHeap((a, b) => a.data < b.data); // create a min heap using the comparison function that compares the data values of nodes let count = 0; // count the number of nodes popped from the heap let median = -1; // let medianIndex = (R * C) / 2; for (let i = 0; i < R; i++) { let temp = new Node(matrix[i][0], i, 0); minHeap.push(temp); } while (count <= medianIndex) { let top = minHeap.pop(); let row = top.row; let col = top.col; median = top.data; count++; if (col + 1 < C) { col++; let temp = new Node(matrix[row][col], row, col); minHeap.push(temp); } } return median; } } let r = 3; let c = 3; let matrix = [ [1, 3, 5], [2, 6, 9], [3, 6, 9], ]; let obj = new Solution(); console.log(obj.median(matrix, r, c)); |
5
Time Complexity = O(log(r*c))- for insertion and deletion in min heap
Auxiliary Space = O((r*c)log(r*c)) – For creating a min heap, with the maximum number of elements equal to r*c/2
This article is contributed by Akshit Agarwal. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please Login to comment...