Given a square matrix mat[][] of size n * n, select two elements such that the second element lies strictly below and strictly to the right of the first element.
Return the maximum possible difference between these two elements.
In other words, for any two elements mat[a][b] and mat[c][d], find the maximum value of mat[c][d] - mat[a][b] such that c > a and d > b.
Examples:
Input: mat = [[1, 2, -1, -4, -20], [-8, -3, 4, 2, 1], [3, 8, 6, 1, 3], [-4, -1, 1, 7, -6], [0, -4, 10, -5, 1]]
Output: 18
Explanation: Choose -8 at position (1, 0) and 10 at position (4, 2). Since the second element is strictly below and strictly to the right of the first element, 10 - (-8) = 18, which is the maximum possible difference.Input: mat = [[5, 4], [3, 2]]
Output: -3
Explanation: The only valid pair is 5 and 2. 2 - 5 = -3. Hence, the maximum possible difference is -3.
Table of Content
[Naive Approach] Try Every Pair - O(n^4) Time and O(1) Space
Every possible pair of positions (a, b) and (c, d) with c > a and d > b can be checked directly, computing mat[c][d] - mat[a][b] for each and tracking the maximum found. Since this involves iterating over every possible first position and then every possible second position that lies strictly below and to the right, the total work grows with the fourth power of the matrix dimension, which becomes very slow for large matrices.
Illustration:
- Take mat = [[5, 4], [3, 2]].
- The only position that has anything strictly below and to the right of it is (0, 0), with value 5.
- The only valid second position is (1, 1), with value 2.
- Computing 2 - 5 gives -3, which is checked against all other pairs, but since no other valid pair exists in this 2x2 matrix, -3 is the final answer.
#include <bits/stdc++.h>
using namespace std;
int findMaxValue(vector<vector<int>>& mat) {
int n = mat.size();
int res = INT_MIN;
// try every valid pair of positions directly
for (int a = 0; a < n; a++) {
for (int b = 0; b < n; b++) {
for (int c = a + 1; c < n; c++) {
for (int d = b + 1; d < n; d++) {
res = max(res, mat[c][d] - mat[a][b]);
}
}
}
}
return res;
}
int main() {
vector<vector<int>> mat = {{5, 4}, {3, 2}};
cout << findMaxValue(mat) << endl;
return 0;
}
class GfG {
static int findMaxValue(int[][] mat) {
int n = mat.length;
int res = Integer.MIN_VALUE;
// try every valid pair of positions directly
for (int a = 0; a < n; a++) {
for (int b = 0; b < n; b++) {
for (int c = a + 1; c < n; c++) {
for (int d = b + 1; d < n; d++) {
res = Math.max(res, mat[c][d] - mat[a][b]);
}
}
}
}
return res;
}
public static void main(String[] args) {
int[][] mat = {{5, 4}, {3, 2}};
System.out.println(findMaxValue(mat));
}
}
def findMaxValue(mat):
n = len(mat)
res = float('-inf')
# try every valid pair of positions directly
for a in range(n):
for b in range(n):
for c in range(a + 1, n):
for d in range(b + 1, n):
res = max(res, mat[c][d] - mat[a][b])
return res
mat = [[5, 4], [3, 2]]
print(findMaxValue(mat))
using System;
class GfG {
static int findMaxValue(int[][] mat) {
int n = mat.Length;
int res = int.MinValue;
// try every valid pair of positions directly
for (int a = 0; a < n; a++) {
for (int b = 0; b < n; b++) {
for (int c = a + 1; c < n; c++) {
for (int d = b + 1; d < n; d++) {
res = Math.Max(res, mat[c][d] - mat[a][b]);
}
}
}
}
return res;
}
static void Main() {
int[][] mat = { new int[]{5, 4}, new int[]{3, 2} };
Console.WriteLine(findMaxValue(mat));
}
}
function findMaxValue(mat) {
const n = mat.length;
let res = -Infinity;
// try every valid pair of positions directly
for (let a = 0; a < n; a++) {
for (let b = 0; b < n; b++) {
for (let c = a + 1; c < n; c++) {
for (let d = b + 1; d < n; d++) {
res = Math.max(res, mat[c][d] - mat[a][b]);
}
}
}
}
return res;
}
// Driver Code
const mat = [[5, 4], [3, 2]];
console.log(findMaxValue(mat));
Output
-3
[Expected Approach] Suffix Maximum (Space Optimized) - O(n^2) Time and O(n) Space
For each position (a,b), the optimal second element is the maximum value strictly below and to the right. Compute these using suffix maxima from the bottom-right to the top-left, ensuring the required maximum is already available when processing a cell. Since each row depends only on the row below, only the current and next suffix-maximum rows need to be stored, reducing memory usage.
Illustration:
- Take mat = [[1,2,-1,-4,-20],[-8,-3,4,2,1],[3,8,6,1,3],[-4,-1,1,7,-6],[0,-4,10,-5,1]].
- Processing starts from the last row (row 4): its suffix maxima from right to left are [10, 10, 10, -5, 1].
- Moving to row 3, at position (3, 0) with value -4, the best value strictly below-right (from the next row's suffix maxima) is checked to update the running answer, and the suffix maximum for the current row is built using both the current row and the row below.
- This process continues upward, and at row 1, position (1, 0) with value -8 is reached; the suffix maximum for the submatrix below-right of it (which includes position (4, 2) with value 10) gives 10 - (-8) = 18.
- Continuing through all remaining positions confirms no pair produces a larger difference, so 18 is the final answer.
#include <bits/stdc++.h>
using namespace std;
int findMaxValue(vector<vector<int>>& mat) {
int n = mat.size();
// only the next row's suffix maxima are
// needed, not the full matrix
vector<int> nextRow(n);
nextRow[n - 1] = mat[n - 1][n - 1];
// fill the last row's suffix maxima from right to left
for (int j = n - 2; j >= 0; j--)
nextRow[j] = max(mat[n - 1][j], nextRow[j + 1]);
int res = INT_MIN;
// process each row from bottom to top,
// keeping only the current and next row
for (int i = n - 2; i >= 0; i--) {
vector<int> curRow(n);
curRow[n - 1] = max(mat[i][n - 1], nextRow[n - 1]);
for (int j = n - 2; j >= 0; j--) {
// update the answer using the best valid
// element strictly below-right
res = max(res, nextRow[j + 1] - mat[i][j]);
// store the suffix maximum for this cell
curRow[j] = max({mat[i][j], nextRow[j], curRow[j + 1], nextRow[j + 1]});
}
nextRow = curRow;
}
return res;
}
int main() {
vector<vector<int>> mat = {
{1, 2, -1, -4, -20},
{-8, -3, 4, 2, 1},
{3, 8, 6, 1, 3},
{-4, -1, 1, 7, -6},
{0, -4, 10, -5, 1}
};
cout << findMaxValue(mat) << endl;
return 0;
}
class GfG {
static int findMaxValue(int[][] mat) {
int n = mat.length;
// only the next row's suffix maxima are
// needed, not the full matrix
int[] nextRow = new int[n];
nextRow[n - 1] = mat[n - 1][n - 1];
// fill the last row's suffix maxima
// from right to left
for (int j = n - 2; j >= 0; j--)
nextRow[j] = Math.max(mat[n - 1][j], nextRow[j + 1]);
int res = Integer.MIN_VALUE;
// process each row from bottom to top,
// keeping only the current and next row
for (int i = n - 2; i >= 0; i--) {
int[] curRow = new int[n];
curRow[n - 1] = Math.max(mat[i][n - 1], nextRow[n - 1]);
for (int j = n - 2; j >= 0; j--) {
// update the answer using the best valid
// ement strictly below-right
res = Math.max(res, nextRow[j + 1] - mat[i][j]);
// store the suffix maximum for this cell
curRow[j] = Math.max(mat[i][j], Math.max(nextRow[j], Math.max(curRow[j + 1], nextRow[j + 1])));
}
nextRow = curRow;
}
return res;
}
public static void main(String[] args) {
int[][] mat = {
{1, 2, -1, -4, -20},
{-8, -3, 4, 2, 1},
{3, 8, 6, 1, 3},
{-4, -1, 1, 7, -6},
{0, -4, 10, -5, 1}
};
System.out.println(findMaxValue(mat));
}
}
def findMaxValue(mat):
n = len(mat)
# only the next row's suffix maxima are needed,
# not the full matrix
nextRow = [0] * n
nextRow[n - 1] = mat[n - 1][n - 1]
# fill the last row's suffix maxima from right to left
for j in range(n - 2, -1, -1):
nextRow[j] = max(mat[n - 1][j], nextRow[j + 1])
res = float('-inf')
# process each row from bottom to top,
# keeping only the current and next row
for i in range(n - 2, -1, -1):
curRow = [0] * n
curRow[n - 1] = max(mat[i][n - 1], nextRow[n - 1])
for j in range(n - 2, -1, -1):
# update the answer using the best valid
# element strictly below-right
res = max(res, nextRow[j + 1] - mat[i][j])
# store the suffix maximum for this cell
curRow[j] = max(mat[i][j], nextRow[j], curRow[j + 1], nextRow[j + 1])
nextRow = curRow
return res
mat = [
[1, 2, -1, -4, -20],
[-8, -3, 4, 2, 1],
[3, 8, 6, 1, 3],
[-4, -1, 1, 7, -6],
[0, -4, 10, -5, 1]
]
print(findMaxValue(mat))
using System;
class GfG {
static int findMaxValue(int[][] mat) {
int n = mat.Length;
// only the next row's suffix maxima are needed,
// not the full matrix
int[] nextRow = new int[n];
nextRow[n - 1] = mat[n - 1][n - 1];
// fill the last row's suffix maxima from right to left
for (int j = n - 2; j >= 0; j--)
nextRow[j] = Math.Max(mat[n - 1][j], nextRow[j + 1]);
int res = int.MinValue;
// process each row from bottom to top,
// keeping only the current and next row
for (int i = n - 2; i >= 0; i--) {
int[] curRow = new int[n];
curRow[n - 1] = Math.Max(mat[i][n - 1], nextRow[n - 1]);
for (int j = n - 2; j >= 0; j--) {
// update the answer using the best valid element strictly below-right
res = Math.Max(res, nextRow[j + 1] - mat[i][j]);
// store the suffix maximum for this cell
curRow[j] = Math.Max(mat[i][j], Math.Max(nextRow[j], Math.Max(curRow[j + 1], nextRow[j + 1])));
}
nextRow = curRow;
}
return res;
}
static void Main() {
int[][] mat = {
new int[]{1, 2, -1, -4, -20},
new int[]{-8, -3, 4, 2, 1},
new int[]{3, 8, 6, 1, 3},
new int[]{-4, -1, 1, 7, -6},
new int[]{0, -4, 10, -5, 1}
};
Console.WriteLine(findMaxValue(mat));
}
}
// Driver Code
function findMaxValue(mat) {
const n = mat.length;
// only the next row's suffix maxima are
// needed, not the full matrix
let nextRow = new Array(n).fill(0);
nextRow[n - 1] = mat[n - 1][n - 1];
// fill the last row's suffix maxima from right to left
for (let j = n - 2; j >= 0; j--)
nextRow[j] = Math.max(mat[n - 1][j], nextRow[j + 1]);
let res = -Infinity;
// process each row from bottom to top,
// keeping only the current and next row
for (let i = n - 2; i >= 0; i--) {
const curRow = new Array(n).fill(0);
curRow[n - 1] = Math.max(mat[i][n - 1], nextRow[n - 1]);
for (let j = n - 2; j >= 0; j--) {
// update the answer using the best
// valid element strictly below-right
res = Math.max(res, nextRow[j + 1] - mat[i][j]);
// store the suffix maximum for this cell
curRow[j] = Math.max(mat[i][j], nextRow[j], curRow[j + 1], nextRow[j + 1]);
}
nextRow = curRow;
}
return res;
}
const mat = [
[1, 2, -1, -4, -20],
[-8, -3, 4, 2, 1],
[3, 8, 6, 1, 3],
[-4, -1, 1, 7, -6],
[0, -4, 10, -5, 1]
];
console.log(findMaxValue(mat));
Output
18