Given a 2D array matrix that is row-wise sorted. The task is to find the median of the given matrix.
Input: matrix=[ [1, 4, 9], [2, 5, 6], [3, 8, 7] ]
Output: 5
Explanation: If we find the linear sorted array, the array becomes 1 2 3 4 5 6 7 8 9. So, median = 5
Input: matrix=[ [1, 3, 8], [2, 3, 4], [1, 2, 5] ]
Output: 3
Explanation:If we find the linear sorted array, the array becomes 1 1 2 2 3 3 4 5 7 8. So, median = 3
Input: matrix=[ [1, 4, 15], [2, 5, 6], [3, 8, 11] ]
The extremely naive approach is to use a linear array or list to store the elements of the given matrix and sort them in increasing manner. The middle element will be the median of matrix.
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
//Function to find the median of the matrix.
int findMedian(vector<vector<int>>& matrix) {
vector<int> lst;
int n = matrix.size();
int m = matrix[0].size();
/* Traverse the matrix and
copy the elements to list*/
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
lst.push_back(matrix[i][j]);
}
}
// Sort the list
sort(lst.begin(), lst.end());
// Return the median element
return lst[(n * m) / 2];
}
};
int main() {
vector<vector<int>> matrix = {
{1, 2, 3, 4, 5},
{8, 9, 11, 12, 13},
{21, 23, 25, 27, 29}
};
//Create an instance of Solution class
Solution sol;
int ans = sol.findMedian(matrix);
//Print the answer
cout << "The median element is: " << ans << endl;
return 0;
}
import java.util.*;
class Solution {
// Function to find the median of the matrix.
public int findMedian(int[][] matrix) {
List<Integer> lst = new ArrayList<>();
int n = matrix.length;
int m = matrix[0].length;
/* Traverse the matrix and
copy the elements to list */
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
lst.add(matrix[i][j]);
}
}
// Sort the list
Collections.sort(lst);
// Return the median element
return lst.get((n * m) / 2);
}
public static void main(String[] args) {
int[][] matrix = {
{1, 2, 3, 4, 5},
{8, 9, 11, 12, 13},
{21, 23, 25, 27, 29}
};
// Create an instance of Solution class
Solution sol = new Solution();
int ans = sol.findMedian(matrix);
// Print the answer
System.out.println("The median element is: " + ans);
}
}
class Solution:
# Function to find the median of the matrix.
def findMedian(self, matrix):
lst = []
n = len(matrix)
m = len(matrix[0])
""" Traverse the matrix and
copy the elements to list """
for i in range(n):
for j in range(m):
lst.append(matrix[i][j])
# Sort the list
lst.sort()
# Return the median element
return lst[(n * m) // 2]
if __name__ == "__main__":
matrix = [
[1, 2, 3, 4, 5],
[8, 9, 11, 12, 13],
[21, 23, 25, 27, 29]
]
# Create an instance of Solution class
sol = Solution()
ans = sol.findMedian(matrix)
# Print the answer
print("The median element is:", ans)
class Solution {
// Function to find the median of the matrix.
findMedian(matrix) {
let lst = [];
let n = matrix.length;
let m = matrix[0].length;
/* Traverse the matrix and
copy the elements to list */
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
lst.push(matrix[i][j]);
}
}
// Sort the list
lst.sort((a, b) => a - b);
// Return the median element
return lst[Math.floor((n * m) / 2)];
}
}
let matrix = [
[1, 2, 3, 4, 5],
[8, 9, 11, 12, 13],
[21, 23, 25, 27, 29]
];
// Create an instance of Solution class
let sol = new Solution();
let ans = sol.findMedian(matrix);
// Print the answer
console.log("The median element is:", ans);
Here, the idea is to use the binary search algorithm to find the median of the matrix. To apply binary search, the search range should be sorted. In this case, the search range is [min, max], where min is the minimum element of the matrix and max is the maximum element of the matrix.
How to check if the current element(mid) is the median:If current element is the median, the number of elements smaller or equal to current element will surely be greater than (M*N) // 2 (integer division).
How to check how many numbers are smaller or equal to an element ‘mid’:#include<bits/stdc++.h>
using namespace std;
class Solution {
private:
//Function to find the upper bound of an element
int upperBound(vector<int>& arr, int x, int m) {
int low = 0, high = m - 1;
int ans = m;
//Apply binary search
while (low <= high) {
int mid = (low + high) / 2;
/* If arr[mid] > x, it
can be a possible answer*/
if (arr[mid] > x) {
ans = mid;
//Look for smaller index on the left
high = mid - 1;
}
else {
low = mid + 1;
}
}
//Return the answer
return ans;
}
/*Function to find the count of
element smaller than x or equal to x*/
int countSmallEqual(vector<vector<int>>& matrix, int n, int m, int x) {
int cnt = 0;
for (int i = 0; i < n; i++) {
cnt += upperBound(matrix[i], x, m);
}
//Returnt the count
return cnt;
}
public:
//Function to find the median in a matrix
int findMedian(vector<vector<int>>& matrix) {
int n = matrix.size();
int m = matrix[0].size();
//Intialize low and high
int low = INT_MAX, high = INT_MIN;
//Point low and high to right elements
for (int i = 0; i < n; i++) {
low = min(low, matrix[i][0]);
high = max(high, matrix[i][m - 1]);
}
int req = (n * m) / 2;
//Perform binary search
while (low <= high) {
int mid = low + (high - low) / 2;
/*Store the count of elements
lesser than or equal to mid*/
int smallEqual = countSmallEqual(matrix, n, m, mid);
if (smallEqual <= req) low = mid + 1;
else high = mid - 1;
}
//Return low as answer
return low;
}
};
int main() {
vector<vector<int>> matrix = {{1, 2, 3, 4, 5},
{8, 9, 11, 12, 13},
{21, 23, 25, 27, 29}};
//Create an instance of Solution class
Solution sol;
int ans = sol.findMedian(matrix);
//Print the output
cout << "The median element is: " << ans << endl;
return 0;
}
import java.util.*;
class Solution {
// Function to find the upper bound of an element
private int upperBound(int[] arr, int x, int m) {
int low = 0, high = m - 1;
int ans = m;
// Apply binary search
while (low <= high) {
int mid = (low + high) / 2;
// If arr[mid] > x, it can be a possible answer
if (arr[mid] > x) {
ans = mid;
// Look for smaller index on the left
high = mid - 1;
} else {
low = mid + 1;
}
}
// Return the answer
return ans;
}
// Function to find the count of elements smaller than or equal to x
private int countSmallEqual(int[][] matrix, int n, int m, int x) {
int cnt = 0;
for (int i = 0; i < n; i++) {
cnt += upperBound(matrix[i], x, m);
}
// Return the count
return cnt;
}
// Function to find the median in a matrix
public int findMedian(int[][] matrix) {
int n = matrix.length;
int m = matrix[0].length;
// Initialize low and high
int low = Integer.MAX_VALUE, high = Integer.MIN_VALUE;
// Point low and high to right elements
for (int i = 0; i < n; i++) {
low = Math.min(low, matrix[i][0]);
high = Math.max(high, matrix[i][m - 1]);
}
int req = (n * m) / 2;
// Perform binary search
while (low <= high) {
int mid = low + (high - low) / 2;
/* Store the count of elements
lesser than or equal to mid */
int smallEqual = countSmallEqual(matrix, n, m, mid);
if (smallEqual <= req) {
low = mid + 1;
} else {
high = mid - 1;
}
}
// Return low as answer
return low;
}
public static void main(String[] args) {
int[][] matrix = {{1, 2, 3, 4, 5},
{8, 9, 11, 12, 13},
{21, 23, 25, 27, 29}};
// Create an instance of Solution class
Solution sol = new Solution();
int ans = sol.findMedian(matrix);
// Print the output
System.out.println("The median element is: " + ans);
}
}
class Solution:
# Function to find the upper bound of an element
def upperBound(self, arr, x, m):
low, high = 0, m - 1
ans = m
# Apply binary search
while low <= high:
mid = (low + high) // 2
# If arr[mid] > x, it can be a possible answer
if arr[mid] > x:
ans = mid
# Look for smaller index on the left
high = mid - 1
else:
low = mid + 1
# Return the answer
return ans
# Function to find the count of elements smaller than or equal to x
def countSmallEqual(self, matrix, n, m, x):
cnt = 0
for i in range(n):
cnt += self.upperBound(matrix[i], x, m)
# Return the count
return cnt
# Function to find the median in a matrix
def findMedian(self, matrix):
n = len(matrix)
m = len(matrix[0])
# Initialize low and high
low = float('inf')
high = float('-inf')
# Point low and high to right elements
for i in range(n):
low = min(low, matrix[i][0])
high = max(high, matrix[i][m - 1])
req = (n * m) // 2
# Perform binary search
while low <= high:
mid = low + (high - low) // 2
""" Store the count of elements
lesser than or equal to mid"""
smallEqual = self.countSmallEqual(matrix, n, m, mid)
if smallEqual <= req:
low = mid + 1
else:
high = mid - 1
# Return low as answer
return low
if __name__ == "__main__":
matrix = [[1, 2, 3, 4, 5],
[8, 9, 11, 12, 13],
[21, 23, 25, 27, 29]]
# Create an instance of Solution class
sol = Solution()
ans = sol.findMedian(matrix)
# Print the output
print(f"The median element is: {ans}")
class Solution {
// Function to find the upper bound of an element
upperBound(arr, x, m) {
let low = 0, high = m - 1;
let ans = m;
// Apply binary search
while (low <= high) {
let mid = Math.floor((low + high) / 2);
// If arr[mid] > x, it can be a possible answer
if (arr[mid] > x) {
ans = mid;
// Look for smaller index on the left
high = mid - 1;
} else {
low = mid + 1;
}
}
// Return the answer
return ans;
}
// Function to find the count of elements smaller than or equal to x
countSmallEqual(matrix, n, m, x) {
let cnt = 0;
for (let i = 0; i < n; i++) {
cnt += this.upperBound(matrix[i], x, m);
}
// Return the count
return cnt;
}
// Function to find the median in a matrix
findMedian(matrix) {
let n = matrix.length;
let m = matrix[0].length;
// Initialize low and high
let low = Number.MAX_SAFE_INTEGER;
let high = Number.MIN_SAFE_INTEGER;
// Point low and high to right elements
for (let i = 0; i < n; i++) {
low = Math.min(low, matrix[i][0]);
high = Math.max(high, matrix[i][m - 1]);
}
let req = Math.floor((n * m) / 2);
// Perform binary search
while (low <= high) {
let mid = low + Math.floor((high - low) / 2);
/* Store the count of elements
lesser than or equal to mid*/
let smallEqual = this.countSmallEqual(matrix, n, m, mid);
if (smallEqual <= req) {
low = mid + 1;
} else {
high = mid - 1;
}
}
// Return low as answer
return low;
}
}
const matrix = [[1, 2, 3, 4, 5],
[8, 9, 11, 12, 13],
[21, 23, 25, 27, 29]];
// Create an instance of Solution class
const sol = new Solution();
console.log(sol.findMedian(matrix));
Q: How do we count elements ≤mid efficiently?
A: Use binary search for each row to count elements ≤mid. For a sorted row, the count is the index of the first element >mid, which can be found in O(logm).
Q: What if the matrix has uneven row lengths?
A: For matrices with variable row lengths, ensure that binary search skips empty rows and counts only valid elements. The logic remains unchanged.
Q: What if we need the median of multiple matrices?
A: Combine all matrices and find the median using a priority queue (min-heap) to maintain the smallest k elements while iterating through the rows.
Q: What if the median needs to be computed in real-time?
A: Maintain a streaming median using two heaps (min-heap and max-heap) to balance elements dynamically as new rows arrive.