Open in App
Not now

# 2D Range Minimum Query in O(1)

• Last Updated : 22 Feb, 2023

Given a matrix mat[][] of size N*M, the task is to find the minimum value in a submatrix of the array, defined by the top-left and bottom-right indices of the submatrix for the given queries.

Example:

Input: N = 4, M = 4, mat[][] = { { 5, 8, 2, 4 }, { 7, 2, 9, 1 }, { 1, 4, 7, 3 }, { 3, 5, 6, 8 } }
queries[][] = {{0, 0, 3, 3}, {1, 1, 2, 2}}
Output:
1
2
Explanation:
For first query, top-left corner at (0, 0) and bottom-right corner at (2, 2), which is the entire input matrix. The minimum value in this submatrix is 1.
For second call, the top-left corner at (1, 1) and bottom-right corner at (2, 2). The minimum value in this submatrix is 2.

One solution to this problem is to use a data structure called a sparse table. A sparse table is a data structure that allows you to perform RMQ in O(1) time after O(nmlogn*logm) preprocessing time.

To build a sparse table for a 2D array, you can follow these steps:

• Preprocess the array to calculate the minimum value for each cell and for each submatrix with a size of 2k * 2l, where k and l are non-negative integers.
• Store the minimum values in a 2D array called the sparse table. The size of the sparse table should be n*m*log(n)*log(m).
• Firstly find the largest value of k such that 2k is less than or equal to the width of the submatrix.
• Then, find the largest value of l such that 2l is less than or equal to the height of the submatrix.
• Using these values, you can look up the minimum value in the sparse table and return it as the result.

Here is a brief example of how to implement a 2D range minimum query using a sparse table in Python:

## C++

 `// C++ code to implement the sparse table`   `#include ` `using` `namespace` `std;`   `const` `int` `N = 100;` `int` `matrix[N][N];` `int` `table[N][N][(``int``)(log2(N) + 1)][(``int``)(log2(N) + 1)];`   `// Function to build the sparse table` `void` `build_sparse_table(``int` `n, ``int` `m)` `{` `    ``// Copy the values of the original matrix` `    ``// to the first element of the table` `    ``for` `(``int` `i = 0; i < n; i++) {` `        ``for` `(``int` `j = 0; j < m; j++) {` `            ``table[i][j][0][0] = matrix[i][j];` `        ``}` `    ``}`   `    ``// Building the table` `    ``for` `(``int` `k = 1; k <= (``int``)(log2(n)); k++) {` `        ``for` `(``int` `i = 0; i + (1 << k) - 1 < n; i++) {` `            ``for` `(``int` `j = 0; j + (1 << k) - 1 < m; j++) {` `                ``table[i][j][k][0] = min(` `                    ``table[i][j][k - 1][0],` `                    ``table[i + (1 << (k - 1))][j][k - 1][0]);` `            ``}` `        ``}` `    ``}`   `    ``for` `(``int` `k = 1; k <= (``int``)(log2(m)); k++) {` `        ``for` `(``int` `i = 0; i < n; i++) {` `            ``for` `(``int` `j = 0; j + (1 << k) - 1 < m; j++) {` `                ``table[i][j][0][k] = min(` `                    ``table[i][j][0][k - 1],` `                    ``table[i][j + (1 << (k - 1))][0][k - 1]);` `            ``}` `        ``}` `    ``}`   `    ``for` `(``int` `k = 1; k <= (``int``)(log2(n)); k++) {` `        ``for` `(``int` `l = 1; l <= (``int``)(log2(m)); l++) {` `            ``for` `(``int` `i = 0; i + (1 << k) - 1 < n; i++) {` `                ``for` `(``int` `j = 0; j + (1 << l) - 1 < m; j++) {` `                    ``table[i][j][k][l] = min(` `                        ``min(table[i][j][k - 1][l - 1],` `                            ``table[i + (1 << (k - 1))][j]` `                                 ``[k - 1][l - 1]),` `                        ``min(table[i][j + (1 << (l - 1))]` `                                 ``[k - 1][l - 1],` `                            ``table[i + (1 << (k - 1))]` `                                 ``[j + (1 << (l - 1))][k - 1]` `                                 ``[l - 1]));` `                ``}` `            ``}` `        ``}` `    ``}` `}`   `// Function to find the maximum value in a submatrix` `int` `rmq(``int` `x1, ``int` `y1, ``int` `x2, ``int` `y2)` `{` `    ``// log2(x2-x1+1) gives the power of 2` `    ``// which is just less than or equal to x2-x1+1` `    ``int` `k = log2(x2 - x1 + 1);` `    ``int` `l = log2(y2 - y1 + 1);`   `    ``// Lookup the value from the table which is` `    ``// the maximum among the 4 submatrices` `    ``return` `max(max(table[x1][y1][k][l],` `                   ``table[x2 - (1 << k) + 1][y1][k][l]),` `               ``max(table[x1][y2 - (1 << l) + 1][k][l],` `                   ``table[x2 - (1 << k) + 1]` `                        ``[y2 - (1 << l) + 1][k][l]));` `}`   `// Function to solve the queries` `void` `solve(``int` `n, ``int` `m, vector >& matrix1,` `           ``int` `q, vector<``int``> queries[])` `{` `    ``int` `i = 0;` `    ``while` `(i < n) {` `        ``int` `j = 0;` `        ``while` `(j < m) {` `            ``matrix[i][j] = matrix1[i][j];` `            ``j++;` `        ``}` `        ``i++;` `    ``}` `    ``build_sparse_table(n, m);` `    ``i = 0;` `    ``while` `(i < q) {` `        ``int` `x1, y1, x2, y2;` `        ``x1 = queries[i][0];` `        ``y1 = queries[i][1];` `        ``x2 = queries[i][2];` `        ``y2 = queries[i][3];` `        ``cout << rmq(x1, y1, x2, y2) << endl;` `        ``i++;` `    ``}` `}`   `// Driver code` `int` `main()` `{` `    ``int` `N = 4, M = 4;` `    ``vector > matrix1 = { { 5, 8, 2, 4 },` `                                     ``{ 7, 2, 9, 1 },` `                                     ``{ 1, 4, 7, 3 },` `                                     ``{ 3, 5, 6, 8 } };` `    ``int` `Q = 2;` `    ``vector<``int``> queries[]` `        ``= { { 0, 0, 3, 3 }, { 1, 1, 2, 2 } };`   `    ``// Function call` `    ``solve(N, M, matrix1, Q, queries);`   `    ``return` `0;` `}`

## Java

 `// Java code to implement the sparse table` `import` `java.util.Scanner;`   `class` `GFG {` `  ``static` `final` `int` `N = ``100``;` `  ``static` `int``[][] matrix = ``new` `int``[N][N];` `  ``static` `int``[][][][] table` `    ``= ``new` `int``[N][N]` `    ``[(``int``)(Math.log(N) / Math.log(``2``) + ``1``)]` `    ``[(``int``)(Math.log(N) / Math.log(``2``) + ``1``)];`   `  ``// Function to build the sparse table` `  ``static` `void` `buildSparseTable(``int` `n, ``int` `m)` `  ``{`   `    ``// Copy the values of the original matrix` `    ``// to the first element of the table` `    ``for` `(``int` `i = ``0``; i < n; i++) {` `      ``for` `(``int` `j = ``0``; j < m; j++) {` `        ``table[i][j][``0``][``0``] = matrix[i][j];` `      ``}` `    ``}`   `    ``// Building the table` `    ``for` `(``int` `k = ``1``;` `         ``k <= (``int``)(Math.log(n) / Math.log(``2``)); k++) {` `      ``for` `(``int` `i = ``0``; i + (``1` `<< k) - ``1` `< n; i++) {` `        ``for` `(``int` `j = ``0``; j + (``1` `<< k) - ``1` `< m; j++) {` `          ``table[i][j][k][``0``]` `            ``= Math.min(table[i][j][k - ``1``][``0``],` `                       ``table[i + (``1` `<< (k - ``1``))]` `                       ``[j][k - ``1``][``0``]);` `        ``}` `      ``}` `    ``}`   `    ``for` `(``int` `k = ``1``;` `         ``k <= (``int``)(Math.log(m) / Math.log(``2``)); k++) {` `      ``for` `(``int` `i = ``0``; i < n; i++) {` `        ``for` `(``int` `j = ``0``; j + (``1` `<< k) - ``1` `< m; j++) {` `          ``table[i][j][``0``][k] = Math.min(` `            ``table[i][j][``0``][k - ``1``],` `            ``table[i][j + (``1` `<< (k - ``1``))][``0``]` `            ``[k - ``1``]);` `        ``}` `      ``}` `    ``}`   `    ``for` `(``int` `k = ``1``;` `         ``k <= (``int``)(Math.log(n) / Math.log(``2``)); k++) {` `      ``for` `(``int` `l = ``1``;` `           ``l <= (``int``)(Math.log(m) / Math.log(``2``));` `           ``l++) {` `        ``for` `(``int` `i = ``0``; i + (``1` `<< k) - ``1` `< n; i++) {` `          ``for` `(``int` `j = ``0``; j + (``1` `<< l) - ``1` `< m;` `               ``j++) {` `            ``table[i][j][k][l] = Math.min(` `              ``Math.min(` `                ``table[i][j][k - ``1``][l - ``1``],` `                ``table[i + (``1` `<< (k - ``1``))][j]` `                ``[k - ``1``][l - ``1``]),` `              ``Math.min(` `                ``table[i][j + (``1` `<< (l - ``1``))]` `                ``[k - ``1``][l - ``1``],` `                ``table[i + (``1` `<< (k - ``1``))]` `                ``[j + (``1` `<< (l - ``1``))]` `                ``[k - ``1``][l - ``1``]));` `          ``}` `        ``}` `      ``}` `    ``}` `  ``}`   `  ``// Function to find the maximum value in a submatrix` `  ``static` `int` `rmq(``int` `x1, ``int` `y1, ``int` `x2, ``int` `y2)` `  ``{` `    ``// log2(x2-x1+1) gives the power of 2` `    ``// which is just less than or equal to x2-x1+1` `    ``int` `k = (``int``)(Math.log(x2 - x1 + ``1``) / Math.log(``2``));` `    ``int` `l = (``int``)(Math.log(y2 - y1 + ``1``) / Math.log(``2``));`   `    ``// Lookup the value from the table which is` `    ``// the maximum among the 4 submatrices` `    ``return` `Math.max(` `      ``Math.max(table[x1][y1][k][l],` `               ``table[x2 - (``1` `<< k) + ``1``][y1][k][l]),` `      ``Math.max(table[x1][y2 - (``1` `<< l) + ``1``][k][l],` `               ``table[x2 - (``1` `<< k) + ``1``]` `               ``[y2 - (``1` `<< l) + ``1``][k][l]));` `  ``}`   `  ``// Function to solve the queries` `  ``static` `void` `solve(``int` `n, ``int` `m, ``int``[][] matrix1, ``int` `q,` `                    ``int``[][] queries)` `  ``{` `    ``for` `(``int` `i = ``0``; i < n; i++) {` `      ``for` `(``int` `j = ``0``; j < m; j++) {` `        ``matrix[i][j] = matrix1[i][j];` `      ``}` `    ``}` `    ``buildSparseTable(n, m);` `    ``for` `(``int` `i = ``0``; i < q; i++) {` `      ``int` `x1, y1, x2, y2;` `      ``x1 = queries[i][``0``];` `      ``y1 = queries[i][``1``];` `      ``x2 = queries[i][``2``];` `      ``y2 = queries[i][``3``];` `      ``System.out.println(rmq(x1, y1, x2, y2));` `    ``}` `  ``}`   `  ``// Driver code` `  ``public` `static` `void` `main(String[] args)` `  ``{` `    ``int` `N = ``4``, M = ``4``;` `    ``int``[][] matrix1 = { { ``5``, ``8``, ``2``, ``4` `},` `                       ``{ ``7``, ``2``, ``9``, ``1` `},` `                       ``{ ``1``, ``4``, ``7``, ``3` `},` `                       ``{ ``3``, ``5``, ``6``, ``8` `} };` `    ``int` `Q = ``2``;` `    ``int``[][] queries` `      ``= { { ``0``, ``0``, ``3``, ``3` `}, { ``1``, ``1``, ``2``, ``2` `} };`   `    ``// Function call` `    ``solve(N, M, matrix1, Q, queries);` `  ``}` `}`   `// This Code is Contributed by Prasad Kandekar(prasad264)`

## Python3

 `# Python code to implement the sparse table` `import` `math`   `N ``=` `100` `matrix ``=` `[[``0` `for` `j ``in` `range``(N)] ``for` `i ``in` `range``(N)]` `table ``=` `[[[[``0` `for` `l ``in` `range``(``int``(math.log2(N)) ``+` `1``)] ``for` `k ``in` `range``(` `    ``int``(math.log2(N)) ``+` `1``)] ``for` `j ``in` `range``(N)] ``for` `i ``in` `range``(N)]`   `# Function to build the sparse table` `def` `build_sparse_table(n, m):` `  `  `    ``# Copy the values of the original matrix` `    ``# to the first element of the table` `    ``for` `i ``in` `range``(n):` `        ``for` `j ``in` `range``(m):` `            ``table[i][j][``0``][``0``] ``=` `matrix[i][j]`   `    ``# Building the table` `    ``for` `k ``in` `range``(``1``, ``int``(math.log2(n)) ``+` `1``):` `        ``for` `i ``in` `range``(n ``-` `(``1` `<< k) ``+` `1``):` `            ``for` `j ``in` `range``(m ``-` `(``1` `<< k) ``+` `1``):` `                ``table[i][j][k][``0``] ``=` `min``(` `                    ``table[i][j][k``-``1``][``0``], table[i``+``(``1` `<< (k``-``1``))][j][k``-``1``][``0``])`   `    ``for` `k ``in` `range``(``1``, ``int``(math.log2(m)) ``+` `1``):` `        ``for` `i ``in` `range``(n):` `            ``for` `j ``in` `range``(m ``-` `(``1` `<< k) ``+` `1``):` `                ``table[i][j][``0``][k] ``=` `min``(` `                    ``table[i][j][``0``][k``-``1``], table[i][j``+``(``1` `<< (k``-``1``))][``0``][k``-``1``])`   `    ``for` `k ``in` `range``(``1``, ``int``(math.log2(n)) ``+` `1``):` `        ``for` `l ``in` `range``(``1``, ``int``(math.log2(m)) ``+` `1``):` `            ``for` `i ``in` `range``(n ``-` `(``1` `<< k) ``+` `1``):` `                ``for` `j ``in` `range``(m ``-` `(``1` `<< l) ``+` `1``):` `                    ``table[i][j][k][l] ``=` `min``(` `                        ``table[i][j][k``-``1``][l``-``1``],` `                        ``table[i``+``(``1` `<< (k``-``1``))][j][k``-``1``][l``-``1``],` `                        ``table[i][j``+``(``1` `<< (l``-``1``))][k``-``1``][l``-``1``],` `                        ``table[i``+``(``1` `<< (k``-``1``))][j``+``(``1` `<< (l``-``1``))][k``-``1``][l``-``1``]` `                    ``)`   `# Function to find the maximum value in a submatrix` `def` `rmq(x1, y1, x2, y2):` `    ``# log2(x2-x1+1) gives the power of 2 which is just less than or equal to x2-x1+1` `    ``k ``=` `int``(math.log2(x2``-``x1``+``1``))` `    ``l ``=` `int``(math.log2(y2``-``y1``+``1``))`   `    ``# Lookup the value from the table which is the maximum among the 4 submatrices` `    ``return` `max``(` `        ``table[x1][y1][k][l],` `        ``table[x2``-``(``1` `<< k)``+``1``][y1][k][l],` `        ``table[x1][y2``-``(``1` `<< l)``+``1``][k][l],` `        ``table[x2``-``(``1` `<< k)``+``1``][y2``-``(``1` `<< l)``+``1``][k][l]` `    ``)`   `# Function to solve the queries` `def` `solve(n, m, matrix1, q, queries):` `    ``for` `i ``in` `range``(n):` `        ``for` `j ``in` `range``(m):` `            ``matrix[i][j] ``=` `matrix1[i][j]` `    ``build_sparse_table(n, m)` `    ``for` `i ``in` `range``(q):` `        ``x1, y1, x2, y2 ``=` `queries[i]` `        ``print``(rmq(x1, y1, x2, y2))`   `N ``=` `4` `M ``=` `4` `matrix1 ``=` `[[``5``, ``8``, ``2``, ``4``], [``7``, ``2``, ``9``, ``1``], [``1``, ``4``, ``7``, ``3``], [``3``, ``5``, ``6``, ``8``]]` `Q ``=` `2` `queries ``=` `[[``0``, ``0``, ``3``, ``3``], [``1``, ``1``, ``2``, ``2``]]`   `# Function call` `solve(N, M, matrix1, Q, queries)`   `# This Code is Contributed by sankar.`

## C#

 `// C# code to implement the sparse table`   `using` `System;`   `public` `class` `GFG {`   `    ``const` `int` `N = 100;` `    ``static` `int``[, ] matrix = ``new` `int``[N, N];` `    ``static` `int``[, , , ] table` `        ``= ``new` `int``[N, N,` `                  ``(``int``)(Math.Log(N) / Math.Log(2) + 1),` `                  ``(``int``)(Math.Log(N) / Math.Log(2) + 1)];`   `    ``// Function to build the sparse table` `    ``static` `void` `buildSparseTable(``int` `n, ``int` `m)` `    ``{`   `        ``// Copy the values of the original matrix` `        ``// to the first element of the table` `        ``for` `(``int` `i = 0; i < n; i++) {` `            ``for` `(``int` `j = 0; j < m; j++) {` `                ``table[i, j, 0, 0] = matrix[i, j];` `            ``}` `        ``}`   `        ``// Building the table` `        ``for` `(``int` `k = 1;` `             ``k <= (``int``)(Math.Log(n) / Math.Log(2)); k++) {` `            ``for` `(``int` `i = 0; i + (1 << k) - 1 < n; i++) {` `                ``for` `(``int` `j = 0; j + (1 << k) - 1 < m; j++) {` `                    ``table[i, j, k, 0]` `                        ``= Math.Min(table[i, j, k - 1, 0],` `                                   ``table[i + (1 << (k - 1)),` `                                         ``j, k - 1, 0]);` `                ``}` `            ``}` `        ``}`   `        ``for` `(``int` `k = 1;` `             ``k <= (``int``)(Math.Log(m) / Math.Log(2)); k++) {` `            ``for` `(``int` `i = 0; i < n; i++) {` `                ``for` `(``int` `j = 0; j + (1 << k) - 1 < m; j++) {` `                    ``table[i, j, 0, k] = Math.Min(` `                        ``table[i, j, 0, k - 1],` `                        ``table[i, j + (1 << (k - 1)), 0,` `                              ``k - 1]);` `                ``}` `            ``}` `        ``}`   `        ``for` `(``int` `k = 1;` `             ``k <= (``int``)(Math.Log(n) / Math.Log(2)); k++) {` `            ``for` `(``int` `l = 1;` `                 ``l <= (``int``)(Math.Log(m) / Math.Log(2));` `                 ``l++) {` `                ``for` `(``int` `i = 0; i + (1 << k) - 1 < n; i++) {` `                    ``for` `(``int` `j = 0; j + (1 << l) - 1 < m;` `                         ``j++) {` `                        ``table[i, j, k, l] = Math.Min(` `                            ``Math.Min(` `                                ``table[i, j, k - 1, l - 1],` `                                ``table[i + (1 << (k - 1)), j,` `                                      ``k - 1, l - 1]),` `                            ``Math.Min(` `                                ``table[i, j + (1 << (l - 1)),` `                                      ``k - 1, l - 1],` `                                ``table[i + (1 << (k - 1)),` `                                      ``j + (1 << (l - 1)),` `                                      ``k - 1, l - 1]));` `                    ``}` `                ``}` `            ``}` `        ``}` `    ``}`   `    ``// Function to find the maximum value in a submatrix` `    ``static` `int` `rmq(``int` `x1, ``int` `y1, ``int` `x2, ``int` `y2)` `    ``{` `        ``// log2(x2-x1+1) gives the power of 2` `        ``// which is just less than or equal to x2-x1+1` `        ``int` `k = (``int``)(Math.Log(x2 - x1 + 1) / Math.Log(2));` `        ``int` `l = (``int``)(Math.Log(y2 - y1 + 1) / Math.Log(2));`   `        ``// Lookup the value from the table which is` `        ``// the maximum among the 4 submatrices` `        ``return` `Math.Max(` `            ``Math.Max(table[x1, y1, k, l],` `                     ``table[x2 - (1 << k) + 1, y1, k, l]),` `            ``Math.Max(table[x1, y2 - (1 << l) + 1, k, l],` `                     ``table[x2 - (1 << k) + 1,` `                           ``y2 - (1 << l) + 1, k, l]));` `    ``}`   `    ``// Function to solve the queries` `    ``static` `void` `solve(``int` `n, ``int` `m, ``int``[, ] matrix1, ``int` `q,` `                      ``int``[, ] queries)` `    ``{` `        ``for` `(``int` `i = 0; i < n; i++) {` `            ``for` `(``int` `j = 0; j < m; j++) {` `                ``matrix[i, j] = matrix1[i, j];` `            ``}` `        ``}` `        ``buildSparseTable(n, m);` `        ``for` `(``int` `i = 0; i < q; i++) {` `            ``int` `x1, y1, x2, y2;` `            ``x1 = queries[i, 0];` `            ``y1 = queries[i, 1];` `            ``x2 = queries[i, 2];` `            ``y2 = queries[i, 3];` `            ``Console.WriteLine(rmq(x1, y1, x2, y2));` `        ``}` `    ``}`   `    ``static` `public` `void` `Main()` `    ``{`   `        ``// Code` `        ``int` `N = 4, M = 4;` `        ``int``[, ] matrix1 = { { 5, 8, 2, 4 },` `                            ``{ 7, 2, 9, 1 },` `                            ``{ 1, 4, 7, 3 },` `                            ``{ 3, 5, 6, 8 } };` `        ``int` `Q = 2;` `        ``int``[, ] queries` `            ``= { { 0, 0, 3, 3 }, { 1, 1, 2, 2 } };`   `        ``// Function call` `        ``solve(N, M, matrix1, Q, queries);` `    ``}` `}`   `// This code is contributed by karthik.`

Output

```1
2```

Time complexity:

• O(N * M * log(N) * log(M)) (To build sparse table)
• O(1) (For Each Query)

Auxiliary Space: O(N * M * log(N) * log(M))

Related Articles:

My Personal Notes arrow_drop_up
Related Articles