22. Median in a Row-wise Sorted Matrix
β GFG solution to find median in a row-wise sorted matrix: efficiently find the median element using binary search on answer technique. π
Last updated
β GFG solution to find median in a row-wise sorted matrix: efficiently find the median element using binary search on answer technique. π
Last updated
The problem can be found at the following link: π Question Link
Given a row-wise sorted matrix mat[][]
of size n*m
, where the number of rows and columns is always odd. Your task is to find the median of the matrix.
The median is the middle element when all matrix elements are arranged in sorted order. Since the total number of elements is always odd, there will be exactly one median element.
Input: mat[][] = [[1, 3, 5],
[2, 6, 9],
[3, 6, 9]]
Output: 5
Explanation: Sorting matrix elements gives us [1, 2, 3
Input: mat[][] = [[2, 4, 9],
[3, 6, 7],
[4, 7, 10]]
Output: 6
Explanation: Sorting matrix elements gives us [2, 3, 4,
Input: mat = [[3], [4], [8]]
Output: 4
Explanation: Sorting matrix elements gives us [3, 4, 8].
Hence, 4 is median (middle element at position 1 in 0-indexed array).
$1 \le n, m \le 400$
$1 \le \text{mat}[i][j] \le 2000$
Both n and m are always odd
The optimal approach uses Binary Search on Answer technique combined with upper_bound to efficiently find the median without actually sorting all elements:
Initialize Search Range:
Find minimum element: lo = min(mat[i][0])
for all rows (leftmost elements).
Find maximum element: hi = max(mat[i][m-1])
for all rows (rightmost elements).
Calculate required position: req = (n * m + 1) / 2
(median position).
Binary Search on Possible Values:
For each candidate value mid
in range [lo, hi]
, count elements β€ mid
.
Use upper_bound
on each row to count elements efficiently.
Count Elements β€ Mid:
For each row, use upper_bound(mat[i].begin(), mat[i].end(), mid)
to find position.
Sum up counts from all rows to get total elements β€ mid
.
Adjust Search Range:
If count < req
: median is larger, so lo = mid + 1
.
Else: median could be mid
or smaller, so hi = mid
.
Convergence:
When lo == hi
, we found the median value.
Key Insight: Since each row is sorted, we can use binary search (upper_bound
) to count elements β€ any value in O(log m) time per row.
Expected Time Complexity: O(32 * n * log(m)), where n is the number of rows and m is the number of columns. The factor 32 comes from the maximum number of binary search iterations needed for the range of possible values (since values are bounded by 2000, we need at most logβ(2000) β 11 iterations, but we use 32 as a safe upper bound). For each iteration, we perform upper_bound on n rows, each taking O(log m) time.
Expected Auxiliary Space Complexity: O(1), as we only use a constant amount of additional space for variables like lo, hi, mid, cnt, and req, regardless of the matrix size.
class Solution {
public:
int median(vector<vector<int>>& mat) {
int n = mat.size(), m = mat[0].size();
int lo = mat[0][0], hi = mat[0][m-1];
for (int i = 1; i < n; i++) {
lo = min(lo, mat[i][0]);
hi = max(hi, mat[i][m-1]);
}
int req = (n * m + 1) >> 1;
while (lo < hi) {
int mid = lo + ((hi - lo) >> 1), cnt = 0;
for (int i = 0; i < n; i++)
cnt += upper_bound(mat[i].begin(), mat[i].end(), mid) - mat[i].begin();
if (cnt < req) lo = mid + 1;
else hi = mid;
}
return lo;
}
};
class Solution {
public int median(int[][] mat) {
int n = mat.length, m = mat[0].length;
int lo = mat[0][0], hi = mat[0][m-1];
for (int i = 1; i < n; i++) {
lo = Math.min(lo, mat[i][0]);
hi = Math.max(hi, mat[i][m-1]);
}
int req = (n * m + 1) / 2;
while (lo < hi) {
int mid = lo + (hi - lo) / 2, cnt = 0;
for (int i = 0; i < n; i++) {
int left = 0, right = m;
while (left < right) {
int center = left + (right - left) / 2;
if (mat[i][center] <= mid) left = center + 1;
else right = center;
}
cnt += left;
}
if (cnt < req) lo = mid + 1;
else hi = mid;
}
return lo;
}
}
import bisect
class Solution:
def median(self, mat):
n, m = len(mat), len(mat[0])
lo = min(row[0] for row in mat)
hi = max(row[m-1] for row in mat)
req = (n * m + 1) // 2
while lo < hi:
mid = (lo + hi) // 2
cnt = sum(bisect.bisect_right(row, mid) for row in mat)
if cnt < req:
lo = mid + 1
else:
hi = mid
return lo
For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: π¬ Any Questions?. Let's make this learning journey more collaborative!
β If you find this helpful, please give this repository a star! β
π‘ O(n)
β‘ Good for sparse matrices
πΎ Extra space for heap
π― Optimized Binary
π’ O(32nlog(m))
π’ O(1)
β Best overall performance
π§ Most complex implementation
class Solution {
public:
int median(vector<vector<int>>& mat) {
int n = mat.size(), m = mat[0].size();
vector<int> all;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
all.push_back(mat[i][j]);
sort(all.begin(), all.end());
return all[(n * m) / 2];
}
};
class Solution {
public:
int median(vector<vector<int>>& mat) {
int n = mat.size(), m = mat[0].size();
priority_queue<pair<int, pair<int, int>>,
vector<pair<int, pair<int, int>>>,
greater<pair<int, pair<int, int>>>> pq;
for (int i = 0; i < n; i++)
pq.push({mat[i][0], {i, 0}});
for (int cnt = 0; cnt < (n * m) / 2; cnt++) {
auto top = pq.top(); pq.pop();
int i = top.second.first, j = top.second.second;
if (j + 1 < m)
pq.push({mat[i][j + 1], {i, j + 1}});
}
return pq.top().first;
}
};
class Solution {
public:
int median(vector<vector<int>>& mat) {
int n = mat.size(), m = mat[0].size();
auto count = [&](int x) {
int cnt = 0;
for (int i = 0; i < n; i++) {
int pos = upper_bound(mat[i].begin(), mat[i].end(), x) - mat[i].begin();
cnt += pos;
}
return cnt;
};
int lo = INT_MAX, hi = INT_MIN;
for (int i = 0; i < n; i++) {
lo = min(lo, mat[i][0]);
hi = max(hi, mat[i][m-1]);
}
int target = (n * m + 1) / 2;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
if (count(mid) >= target) hi = mid - 1;
else lo = mid + 1;
}
return lo;
}
};
π Approach
β±οΈ Time Complexity
πΎ Space Complexity
β Pros
β οΈ Cons
π― Binary Search
π’ O(32nlog(m))
π’ O(1)
π Optimal for sorted matrix
π§ Complex logic
π Linear Search
π΄ O(nmlog(n*m))
π΄ O(n*m)
π Simple implementation
π High time & space complexity
π Priority Queue
π― Scenario
ποΈ Recommended Approach
π₯ Performance Rating
π Large sorted matrices
π₯ Binary Search
β β β β β
π Small matrices/Simplicity
π₯ Linear Search
β β β ββ
π§ Memory constrained
π₯ Binary Search
β β β β β
π― Interview/Competitive
π Optimized Binary
β β β β β
π‘ O(nmlog(n))