# Maximize median of a KxK sub-grid in an NxN grid

• Difficulty Level : Expert
• Last Updated : 28 Jul, 2021

Given a square matrix arr[][] of size N consisting of non-negative integers and an integer K, the task is to find the maximum median value of the elements of a square submatrix of the size K.

Examples:

Input: arr[][] = {{1, 5, 12}, {6, 7, 11}, {8, 9, 10}}, N = 3, K = 2
Output: 9
Explanation:
The median of all subsquare of size 2*2 are:

1. The subsquare {{1, 5}, {6, 7}} has the median equal to 5.
2. The subsquare {{5, 12}, {7, 11}} has the median equal to 7.
3. The subsquare {{6, 7}, {8, 9}} has the median equal to 7.
4. The subsquare {{7, 11}, {9, 10}} has the median equal to 9.

Therefore, the maximum possible median value among all possible square matrix is equal to 9.

Input: arr[][] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 10, 11}, {12, 13, 14, 13}}, N = 4, K = 2
Output: 11

Naive Approach: The simplest approach to solve the given above problem is to iterate over every submatrix of size K*K and then find the maximum median among all the submatrix formed.

Time Complexity: O(N2 * K2)
Auxiliary Space: O(1)

Efficient Approach: The above problem can be optimized based on the following observations:

• If M is the median of a square submatrix, then the count of numbers less than or equal to the M in that submatrix must be less than (K2+1)/2.
• The idea is to use Binary Search to find the given median value as:
• If the count of numbers less than M in any submatrix of size K×K is less than (K2+1)/2, then increment the left boundary.
• Otherwise, decrement the right boundary.
• The idea is to use the prefix sum for the matrix to count the elements less than a particular value in constant time in a square submatrix.

Follow the steps below to solve the problem:

• Initialize two variables, say low as 0 and high as INT_MAX representing the range of the search space.
• Iterate until low is less than high and perform the following steps:
• Find the mid-value of the range [low, high] and store it in a variable say mid.
• Initialize vector of vectors say Pre to store the count of element less than or equal to mid in a prefix submatrix.
• Iterate over every element of the matrix arr[][] using variable i and j and update the value of Pre[i + 1][j + 1] as Pre[i + 1][j] + Pre[i][j + 1] – Pre[i][j] and then increment Pre[i + 1][j + 1] by 1 if arr[i][j] is less than or equal to mid.
• Initialize a variable, say flag as false to store if the value of mid is possible or not as the median.
• Iterate over every possible value of pair (i, j) of [K, N]*[K, N] and then perform the following steps:
• Find the count of elements less than or equal to mid in the square submatrix with top-left vertex as (i – K, j – K) and bottom right vertex as (i, j) and then store it in a variable say X as Pre[i][j] – Pre[i – K][j] – Pre[i][j – K]+ Pre[i – K][j – K].
• If X is less than (K2+1)/2 then mark flag true and break out of the loop.
• If the flag is true then update the value of low as (mid + 1). Otherwise, update the value of high as mid.
• After completing the above steps, print the value of low as the maximum median obtained among all possible square submatrix of size K*K.

Below is the implementation of the above approach:

## C++

 `// C++ program for the above approach` `#include ``using` `namespace` `std;` `// Function to determine if a given``// value can be median``bool` `isMaximumMedian(vector >& arr,``                     ``int` `N, ``int` `K, ``int` `mid)``{``    ``// Stores the prefix sum array``    ``vector > Pre(``        ``N + 5, vector<``int``>(N + 5, 0));` `    ``// Traverse the matrix arr[][]``    ``for` `(``int` `i = 0; i < N; ++i) {``        ``for` `(``int` `j = 0; j < N; ++j) {` `            ``// Update Pre[i+1][j+1]``            ``Pre[i + 1][j + 1] = Pre[i + 1][j]``                                ``+ Pre[i][j + 1]``                                ``- Pre[i][j];` `            ``// If arr[i][j] is less``            ``// than or equal to mid``            ``if` `(arr[i][j] <= mid)``                ``Pre[i + 1][j + 1]++;``        ``}``    ``}` `    ``// Stores the count of elements``    ``// should be less than mid``    ``int` `required = (K * K + 1) / 2;` `    ``// Stores if the median mid``    ``// can be possible or not``    ``bool` `flag = 0;` `    ``// Iterate over the range [K, N]``    ``for` `(``int` `i = K; i <= N; ++i) {` `        ``// Iterate over the range [K, N]``        ``for` `(``int` `j = K; j <= N; ++j) {` `            ``// Stores count of elements less``            ``// than or equal to the value``            ``// mid in submatrix with bottom``            ``// right vertices at (i, j)``            ``int` `X = Pre[i][j] - Pre[i - K][j]``                    ``- Pre[i][j - K]``                    ``+ Pre[i - K][j - K];` `            ``// If X is less than or``            ``// equal to required``            ``if` `(X < required)``                ``flag = 1;``        ``}``    ``}` `    ``// Return flag``    ``return` `flag;``}` `// Function to find the maximum median``// of a subsquare of the given size``int` `maximumMedian(vector >& arr,``                  ``int` `N, ``int` `K)``{``    ``// Stores the range of the``    ``// search space``    ``int` `low = 0, high = 1e9;` `    ``// Iterate until low is less``    ``// than high``    ``while` `(low < high) {` `        ``// Stores the mid value of``        ``// the range [low, high]``        ``int` `mid = low + (high - low) / 2;` `        ``// If the current median can``        ``// be possible``        ``if` `(isMaximumMedian(arr, N, K, mid)) {` `            ``// Update the value of low``            ``low = mid + 1;``        ``}``        ``else` `{` `            ``// Update the value of high``            ``high = mid;``        ``}``    ``}` `    ``// Return value stored in low as``    ``// answer``    ``return` `low;``}` `// Driver Code``int` `main()``{``    ``vector > arr``        ``= { { 1, 5, 12 }, { 6, 7, 11 }, { 8, 9, 10 } };``    ``int` `N = arr.size();``    ``int` `K = 2;``    ``cout << maximumMedian(arr, N, K);` `    ``return` `0;``}`

## Java

 `// Java program for the above approach``public` `class` `GFG``{` `// Function to determine if a given``// value can be median``static` `boolean` `isMaximumMedian(``int` `arr[][] , ``int` `N, ``int` `K, ``int` `mid)``{``  ` `    ``// Stores the prefix sum array``    ``int` `[][]Pre = ``new` `int` `[N+``5``][N+``5``];` `    ``// Traverse the matrix arr[][]``    ``for` `(``int` `i = ``0``; i < N; ++i) {``        ``for` `(``int` `j = ``0``; j < N; ++j) {` `            ``// Update Pre[i+1][j+1]``            ``Pre[i + ``1``][j + ``1``] = Pre[i + ``1``][j]``                                ``+ Pre[i][j + ``1``]``                                ``- Pre[i][j];` `            ``// If arr[i][j] is less``            ``// than or equal to mid``            ``if` `(arr[i][j] <= mid)``                ``Pre[i + ``1``][j + ``1``]++;``        ``}``    ``}` `    ``// Stores the count of elements``    ``// should be less than mid``    ``int` `required = (K * K + ``1``) / ``2``;` `    ``// Stores if the median mid``    ``// can be possible or not``    ``boolean` `flag = ``false``;` `    ``// Iterate over the range [K, N]``    ``for` `(``int` `i = K; i <= N; ++i) {` `        ``// Iterate over the range [K, N]``        ``for` `(``int` `j = K; j <= N; ++j) {` `            ``// Stores count of elements less``            ``// than or equal to the value``            ``// mid in submatrix with bottom``            ``// right vertices at (i, j)``            ``int` `X = Pre[i][j] - Pre[i - K][j]``                    ``- Pre[i][j - K]``                    ``+ Pre[i - K][j - K];` `            ``// If X is less than or``            ``// equal to required``            ``if` `(X < required)``                ``flag = ``true``;``        ``}``    ``}` `    ``// Return flag``    ``return` `flag;``}` `// Function to find the maximum median``// of a subsquare of the given size``static` `int` `maximumMedian(``int` `arr[][], ``int` `N, ``int` `K)``{``    ``// Stores the range of the``    ``// search space``    ``int` `low = ``0``, high = (``int``)1e9;` `    ``// Iterate until low is less``    ``// than high``    ``while` `(low < high) {` `        ``// Stores the mid value of``        ``// the range [low, high]``        ``int` `mid = low + (high - low) / ``2``;` `        ``// If the current median can``        ``// be possible``        ``if` `(isMaximumMedian(arr, N, K, mid)) {` `            ``// Update the value of low``            ``low = mid + ``1``;``        ``}``        ``else` `{` `            ``// Update the value of high``            ``high = mid;``        ``}``    ``}` `    ``// Return value stored in low as``    ``// answer``    ``return` `low;``}` `// Driver Code``public` `static` `void` `main(String args[])``{``   ``int` `[][] arr = { { ``1``, ``5``, ``12` `}, { ``6``, ``7``, ``11` `}, { ``8``, ``9``, ``10` `} };``    ``int` `N = arr.length;``    ``int` `K = ``2``;``    ``System.out.print( maximumMedian(arr, N, K));``}``}` `// This code is contributed by SoumikMondal`

## Python3

 `# Python3 program for the above approach` `# Function to determine if a given``# value can be median``def` `isMaximumMedian(arr, N, K, mid):``    ` `    ``# Stores the prefix sum array``    ``Pre ``=` `[[``0` `for` `x ``in` `range``(N ``+` `5``)]``              ``for` `y ``in` `range``(N ``+` `5``)]` `    ``# Traverse the matrix arr[][]``    ``for` `i ``in` `range``(N):``        ``for` `j ``in` `range``(N):` `            ``# Update Pre[i+1][j+1]``            ``Pre[i ``+` `1``][j ``+` `1``] ``=` `(Pre[i ``+` `1``][j] ``+``                                 ``Pre[i][j ``+` `1``] ``-``                                 ``Pre[i][j])` `            ``# If arr[i][j] is less``            ``# than or equal to mid``            ``if` `(arr[i][j] <``=` `mid):``                ``Pre[i ``+` `1``][j ``+` `1``] ``+``=` `1` `    ``# Stores the count of elements``    ``# should be less than mid``    ``required ``=` `(K ``*` `K ``+` `1``) ``/``/` `2` `    ``# Stores if the median mid``    ``# can be possible or not``    ``flag ``=` `0` `    ``# Iterate over the range [K, N]``    ``for` `i ``in` `range``(K, N ``+` `1``):` `        ``# Iterate over the range [K, N]``        ``for` `j ``in` `range``(K, N ``+` `1``):` `            ``# Stores count of elements less``            ``# than or equal to the value``            ``# mid in submatrix with bottom``            ``# right vertices at (i, j)``            ``X ``=` `(Pre[i][j] ``-` `Pre[i ``-` `K][j] ``-``                 ``Pre[i][j ``-` `K] ``+` `Pre[i ``-` `K][j ``-` `K])` `            ``# If X is less than or``            ``# equal to required``            ``if` `(X < required):``                ``flag ``=` `1` `    ``# Return flag``    ``return` `flag` `# Function to find the maximum median``# of a subsquare of the given size``def` `maximumMedian(arr, N, K):``    ` `    ``# Stores the range of the``    ``# search space``    ``low ``=` `0``    ``high ``=` `1000000009` `    ``# Iterate until low is less``    ``# than high``    ``while` `(low < high):` `        ``# Stores the mid value of``        ``# the range [low, high]``        ``mid ``=` `low ``+` `(high ``-` `low) ``/``/` `2` `        ``# If the current median can``        ``# be possible``        ``if` `(isMaximumMedian(arr, N, K, mid)):` `            ``# Update the value of low``            ``low ``=` `mid ``+` `1` `        ``else``:` `            ``# Update the value of high``            ``high ``=` `mid` `    ``# Return value stored in low as``    ``# answer``    ``return` `low` `# Driver Code``if` `__name__ ``=``=` `"__main__"``:` `    ``arr ``=` `[ [ ``1``, ``5``, ``12` `],``            ``[ ``6``, ``7``, ``11` `],``            ``[ ``8``, ``9``, ``10` `] ]``    ``N ``=` `len``(arr)``    ``K ``=` `2``    ` `    ``print``(maximumMedian(arr, N, K))` `# This code is contributed by ukasp`

## C#

 `// C# program for the above approach``using` `System;` `class` `GFG{` `// Function to determine if a given``// value can be median``static` `bool` `isMaximumMedian(``int``[,] arr, ``int` `N,``                            ``int` `K, ``int` `mid)``{``    ` `    ``// Stores the prefix sum array``    ``int` `[,]Pre = ``new` `int``[N + 5, N + 5];` `    ``// Traverse the matrix arr[][]``    ``for``(``int` `i = 0; i < N; ++i)``    ``{``        ``for``(``int` `j = 0; j < N; ++j)``        ``{``            ` `            ``// Update Pre[i+1][j+1]``            ``Pre[i + 1, j + 1] = Pre[i + 1, j] +``                                ``Pre[i, j + 1] -``                                ``Pre[i, j];` `            ``// If arr[i][j] is less``            ``// than or equal to mid``            ``if` `(arr[i, j] <= mid)``                ``Pre[i + 1, j + 1]++;``        ``}``    ``}` `    ``// Stores the count of elements``    ``// should be less than mid``    ``int` `required = (K * K + 1) / 2;` `    ``// Stores if the median mid``    ``// can be possible or not``    ``bool` `flag = ``false``;` `    ``// Iterate over the range [K, N]``    ``for``(``int` `i = K; i <= N; ++i)``    ``{``        ` `        ``// Iterate over the range [K, N]``        ``for``(``int` `j = K; j <= N; ++j)``        ``{``            ` `            ``// Stores count of elements less``            ``// than or equal to the value``            ``// mid in submatrix with bottom``            ``// right vertices at (i, j)``            ``int` `X = Pre[i, j] - Pre[i - K, j] -``                    ``Pre[i, j - K] + Pre[i - K, j - K];` `            ``// If X is less than or``            ``// equal to required``            ``if` `(X < required)``                ``flag = ``true``;``        ``}``    ``}` `    ``// Return flag``    ``return` `flag;``}` `// Function to find the maximum median``// of a subsquare of the given size``static` `int` `maximumMedian(``int``[,] arr, ``int` `N, ``int` `K)``{``    ` `    ``// Stores the range of the``    ``// search space``    ``int` `low = 0, high = (``int``)1e9;` `    ``// Iterate until low is less``    ``// than high``    ``while` `(low < high)``    ``{``        ` `        ``// Stores the mid value of``        ``// the range [low, high]``        ``int` `mid = low + (high - low) / 2;` `        ``// If the current median can``        ``// be possible``        ``if` `(isMaximumMedian(arr, N, K, mid))``        ``{``            ` `            ``// Update the value of low``            ``low = mid + 1;``        ``}``        ``else``        ``{``            ` `            ``// Update the value of high``            ``high = mid;``        ``}``    ``}` `    ``// Return value stored in low as``    ``// answer``    ``return` `low;``}` `// Driver code``public` `static` `void` `Main(``string``[] args)``{``    ``int` `[,] arr = { { 1, 5, 12 },``                    ``{ 6, 7, 11 },``                    ``{ 8, 9, 10 } };``    ``int` `N = arr.GetLength(0);``    ``int` `K = 2;``    ` `    ``Console.WriteLine(maximumMedian(arr, N, K));``}``}` `// This code is contributed by avijitmondal1998`

## Javascript

 ``

Output:

`9`

Time Complexity: O(N2 * log(109))
Auxiliary Space: O(N2)

My Personal Notes arrow_drop_up