Related Articles

# 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)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

My Personal Notes arrow_drop_up