3567. Minimum Absolute Difference in Sliding Submatrix
Problem Description
You are given a 2D integer matrix grid
with dimensions m x n
and an integer k
. Your task is to find the minimum absolute difference between any two distinct values within every possible k x k
square submatrix of the grid.
For each k x k
submatrix in the grid, you need to:
- Find all pairs of distinct values within that submatrix
- Calculate the absolute difference for each pair
- Determine the minimum absolute difference among all pairs
The result should be a 2D array ans
with dimensions (m - k + 1) x (n - k + 1)
, where each element ans[i][j]
represents the minimum absolute difference for the k x k
submatrix that starts at position (i, j)
in the original grid (with (i, j)
being the top-left corner of the submatrix).
Special case: If all elements in a submatrix are identical (no distinct pairs exist), the minimum absolute difference for that submatrix is 0.
For example, if you have a 4x4 grid and k=2, you would examine all possible 2x2 submatrices:
- The submatrix starting at (0,0) covers positions (0,0), (0,1), (1,0), (1,1)
- The submatrix starting at (0,1) covers positions (0,1), (0,2), (1,1), (1,2)
- And so on...
Each of these submatrices would contribute one value to the result array based on the minimum absolute difference between its distinct elements.
Intuition
The key insight is that to find the minimum absolute difference between any two distinct values, we need to compare all possible pairs within each submatrix. However, comparing all pairs directly would be inefficient.
Think about what happens when we have a list of numbers and want to find the smallest difference between any two of them. If we sort the numbers first, the minimum difference must occur between two adjacent elements in the sorted list. Why? Because for any two non-adjacent elements in a sorted array, there's always an element between them that would create a smaller difference with one of them.
For example, if we have sorted values [1, 3, 7, 9]
, the minimum difference could be between (1,3)
, (3,7)
, or (7,9)
. We don't need to check (1,7)
or (1,9)
because 3
is closer to both 1
and 7
than they are to each other.
This leads us to the approach:
- For each
k x k
submatrix, extract all its elements - Sort these elements
- Check only consecutive pairs in the sorted list (using
pairwise
) - Skip pairs where both elements are the same (we need distinct values)
- Find the minimum among these differences
The time complexity for each submatrix becomes O(kΒ² log kΒ²)
for sorting plus O(kΒ²)
for finding the minimum difference, which is much better than checking all O(kβ΄)
possible pairs without sorting.
The edge case where all elements are identical is handled naturally - when we filter for distinct pairs (if a != b
), no pairs remain, so we default to 0.
Learn more about Sorting patterns.
Solution Approach
The solution follows a straightforward enumeration approach where we systematically examine each possible k x k
submatrix in the grid.
Step 1: Initialize the result array
ans = [[0] * (n - k + 1) for _ in range(m - k + 1)]
We create a 2D array ans
with dimensions (m - k + 1) x (n - k + 1)
to store the results. This size corresponds to the number of possible top-left positions for a k x k
submatrix in an m x n
grid.
Step 2: Enumerate all possible submatrices
for i in range(m - k + 1):
for j in range(n - k + 1):
We iterate through all valid top-left corner positions (i, j)
where a k x k
submatrix can fit within the grid boundaries.
Step 3: Extract elements from each submatrix
nums = []
for x in range(i, i + k):
for y in range(j, j + k):
nums.append(grid[x][y])
For each submatrix starting at (i, j)
, we collect all kΒ²
elements into a list nums
. The nested loops iterate from row i
to i + k - 1
and column j
to j + k - 1
.
Step 4: Sort and find minimum difference
nums.sort()
d = min((abs(a - b) for a, b in pairwise(nums) if a != b), default=0)
After sorting the elements, we use pairwise(nums)
to generate consecutive pairs from the sorted list. The pairwise
function creates pairs like (nums[0], nums[1])
, (nums[1], nums[2])
, etc. We calculate the absolute difference for each pair where the elements are distinct (a != b
), and find the minimum among these differences. If no distinct pairs exist (all elements are the same), the default=0
parameter ensures we return 0.
Step 5: Store the result
ans[i][j] = d
We store the minimum absolute difference for the current submatrix at the corresponding position in our result array.
The algorithm processes a total of (m - k + 1) Γ (n - k + 1)
submatrices, and for each submatrix, it performs sorting on kΒ²
elements, resulting in an overall time complexity of O((m - k + 1) Γ (n - k + 1) Γ kΒ² log kΒ²)
.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a concrete example to illustrate the solution approach.
Consider a 4Γ4 grid with k = 3:
grid = [[5, 2, 9], [3, 8, 1], [7, 4, 6]]
We need to find the minimum absolute difference for each possible 3Γ3 submatrix. With a 4Γ4 grid and k=3, we have (4-3+1) Γ (4-3+1) = 2Γ2 = 4 possible submatrices.
Wait, let me correct that. For a 3Γ3 grid with k=3, we actually have (3-3+1) Γ (3-3+1) = 1Γ1 = 1 possible submatrix (the entire grid itself).
Let me use a better example with a 4Γ4 grid and k=2:
grid = [[5, 2, 9, 3], [3, 8, 1, 4], [7, 4, 6, 2], [1, 5, 3, 8]]
With k=2, we'll have (4-2+1) Γ (4-2+1) = 3Γ3 = 9 possible 2Γ2 submatrices.
Submatrix at position (0,0):
- Top-left corner: (0,0)
- Elements: [5, 2, 3, 8]
- After sorting: [2, 3, 5, 8]
- Consecutive pairs: (2,3), (3,5), (5,8)
- Differences: |3-2|=1, |5-3|=2, |8-5|=3
- Minimum difference: 1
Submatrix at position (0,1):
- Top-left corner: (0,1)
- Elements: [2, 9, 8, 1]
- After sorting: [1, 2, 8, 9]
- Consecutive pairs: (1,2), (2,8), (8,9)
- Differences: |2-1|=1, |8-2|=6, |9-8|=1
- Minimum difference: 1
Submatrix at position (1,2):
- Top-left corner: (1,2)
- Elements: [1, 4, 6, 2]
- After sorting: [1, 2, 4, 6]
- Consecutive pairs: (1,2), (2,4), (4,6)
- Differences: |2-1|=1, |4-2|=2, |6-4|=2
- Minimum difference: 1
Following this process for all 9 submatrices, our result array would be:
ans = [[1, 1, 1], [1, 2, 1], [2, 2, 3]]
Special case example: If we had a submatrix with all identical elements like [5, 5, 5, 5]:
- After sorting: [5, 5, 5, 5]
- Consecutive pairs: (5,5), (5,5), (5,5)
- Since we filter out pairs where a == b, no valid pairs remain
- The
default=0
parameter gives us 0 as the result
This walkthrough demonstrates how the algorithm systematically processes each submatrix by extracting elements, sorting them, and efficiently finding the minimum difference between distinct values using consecutive pairs in the sorted list.
Solution Implementation
1from typing import List
2from itertools import pairwise
3
4class Solution:
5 def minAbsDiff(self, grid: List[List[int]], k: int) -> List[List[int]]:
6 # Get dimensions of the grid
7 rows, cols = len(grid), len(grid[0])
8
9 # Initialize result matrix with dimensions for all possible kΓk subgrids
10 result = [[0] * (cols - k + 1) for _ in range(rows - k + 1)]
11
12 # Iterate through all possible starting positions for kΓk subgrids
13 for start_row in range(rows - k + 1):
14 for start_col in range(cols - k + 1):
15 # Collect all values from the current kΓk subgrid
16 subgrid_values = []
17 for row in range(start_row, start_row + k):
18 for col in range(start_col, start_col + k):
19 subgrid_values.append(grid[row][col])
20
21 # Sort values to find minimum difference between consecutive elements
22 subgrid_values.sort()
23
24 # Calculate minimum absolute difference between any two distinct values
25 # Using pairwise to get consecutive pairs after sorting
26 min_difference = min(
27 (abs(first - second)
28 for first, second in pairwise(subgrid_values)
29 if first != second),
30 default=0
31 )
32
33 # Store the minimum difference for this subgrid
34 result[start_row][start_col] = min_difference
35
36 return result
37
1class Solution {
2 /**
3 * Finds the minimum absolute difference between any two distinct elements
4 * in each k x k subgrid of the given grid.
5 *
6 * @param grid The input 2D grid of integers
7 * @param k The size of the square subgrid
8 * @return A 2D array where each element represents the minimum absolute difference
9 * for the corresponding k x k subgrid (0 if all elements are the same)
10 */
11 public int[][] minAbsDiff(int[][] grid, int k) {
12 int rows = grid.length;
13 int cols = grid[0].length;
14
15 // Result array to store minimum absolute differences for each subgrid
16 int[][] result = new int[rows - k + 1][cols - k + 1];
17
18 // Iterate through all possible starting positions for k x k subgrids
19 for (int startRow = 0; startRow <= rows - k; startRow++) {
20 for (int startCol = 0; startCol <= cols - k; startCol++) {
21
22 // Collect all elements from the current k x k subgrid
23 List<Integer> subgridElements = new ArrayList<>();
24 for (int row = startRow; row < startRow + k; row++) {
25 for (int col = startCol; col < startCol + k; col++) {
26 subgridElements.add(grid[row][col]);
27 }
28 }
29
30 // Sort elements to find minimum difference between adjacent elements
31 Collections.sort(subgridElements);
32
33 // Find minimum absolute difference between any two distinct elements
34 int minDifference = Integer.MAX_VALUE;
35 for (int index = 1; index < subgridElements.size(); index++) {
36 int previousElement = subgridElements.get(index - 1);
37 int currentElement = subgridElements.get(index);
38
39 // Only consider distinct elements
40 if (previousElement != currentElement) {
41 minDifference = Math.min(minDifference,
42 Math.abs(previousElement - currentElement));
43 }
44 }
45
46 // If no distinct elements found (all elements are the same), set to 0
47 result[startRow][startCol] = (minDifference == Integer.MAX_VALUE) ? 0 : minDifference;
48 }
49 }
50
51 return result;
52 }
53}
54
1class Solution {
2public:
3 vector<vector<int>> minAbsDiff(vector<vector<int>>& grid, int k) {
4 int rows = grid.size();
5 int cols = grid[0].size();
6
7 // Initialize result matrix with dimensions (rows - k + 1) x (cols - k + 1)
8 vector<vector<int>> result(rows - k + 1, vector<int>(cols - k + 1, 0));
9
10 // Iterate through all possible k x k subgrids
11 for (int startRow = 0; startRow <= rows - k; ++startRow) {
12 for (int startCol = 0; startCol <= cols - k; ++startCol) {
13
14 // Collect all elements from the current k x k subgrid
15 vector<int> subgridElements;
16 for (int row = startRow; row < startRow + k; ++row) {
17 for (int col = startCol; col < startCol + k; ++col) {
18 subgridElements.push_back(grid[row][col]);
19 }
20 }
21
22 // Sort elements to find minimum absolute difference between adjacent distinct values
23 sort(subgridElements.begin(), subgridElements.end());
24
25 // Find minimum absolute difference between consecutive distinct elements
26 int minDifference = INT_MAX;
27 for (int i = 1; i < subgridElements.size(); ++i) {
28 // Only consider distinct consecutive elements
29 if (subgridElements[i] != subgridElements[i - 1]) {
30 int currentDifference = abs(subgridElements[i] - subgridElements[i - 1]);
31 minDifference = min(minDifference, currentDifference);
32 }
33 }
34
35 // If no distinct elements found (all elements are same), set difference to 0
36 result[startRow][startCol] = (minDifference == INT_MAX) ? 0 : minDifference;
37 }
38 }
39
40 return result;
41 }
42};
43
1/**
2 * Finds the minimum absolute difference between any two distinct elements
3 * in each kΓk subgrid of the input grid
4 * @param grid - The input 2D grid of numbers
5 * @param k - The size of the square subgrid
6 * @returns A 2D array where each element represents the minimum absolute difference
7 * for the corresponding kΓk subgrid (0 if all elements are the same)
8 */
9function minAbsDiff(grid: number[][], k: number): number[][] {
10 const rows: number = grid.length;
11 const cols: number = grid[0].length;
12
13 // Initialize result matrix with dimensions (rows - k + 1) Γ (cols - k + 1)
14 const result: number[][] = Array.from(
15 { length: rows - k + 1 },
16 () => Array(cols - k + 1).fill(0)
17 );
18
19 // Iterate through all possible kΓk subgrid starting positions
20 for (let row = 0; row <= rows - k; row++) {
21 for (let col = 0; col <= cols - k; col++) {
22 // Extract all elements from the current kΓk subgrid
23 const subgridElements: number[] = [];
24 for (let subRow = row; subRow < row + k; subRow++) {
25 for (let subCol = col; subCol < col + k; subCol++) {
26 subgridElements.push(grid[subRow][subCol]);
27 }
28 }
29
30 // Sort elements to find minimum difference between adjacent distinct values
31 subgridElements.sort((a, b) => a - b);
32
33 // Find minimum absolute difference between distinct elements
34 let minDifference: number = Number.MAX_SAFE_INTEGER;
35 for (let index = 1; index < subgridElements.length; index++) {
36 // Only consider differences between distinct elements
37 if (subgridElements[index] !== subgridElements[index - 1]) {
38 const currentDifference: number = Math.abs(
39 subgridElements[index] - subgridElements[index - 1]
40 );
41 minDifference = Math.min(minDifference, currentDifference);
42 }
43 }
44
45 // Store result: 0 if all elements are the same, otherwise the minimum difference
46 result[row][col] = minDifference === Number.MAX_SAFE_INTEGER ? 0 : minDifference;
47 }
48 }
49
50 return result;
51}
52
Time and Space Complexity
Time Complexity: O((m - k + 1) Γ (n - k + 1) Γ kΒ² Γ log(k))
The analysis breaks down as follows:
- The outer two loops iterate through all possible
k Γ k
submatrices, giving us(m - k + 1) Γ (n - k + 1)
iterations - For each submatrix position, we extract
kΒ²
elements using two nested loops (lines 8-10) - Sorting these
kΒ²
elements takesO(kΒ² Γ log(kΒ²))
=O(kΒ² Γ log(k))
time - The pairwise comparison to find minimum absolute difference iterates through
O(kΒ²)
consecutive pairs in the sorted array - Overall:
O((m - k + 1) Γ (n - k + 1) Γ (kΒ² + kΒ² Γ log(k) + kΒ²))
=O((m - k + 1) Γ (n - k + 1) Γ kΒ² Γ log(k))
Space Complexity: O(kΒ²)
The space analysis:
- The
ans
matrix usesO((m - k + 1) Γ (n - k + 1))
space, but this is the output and typically not counted in auxiliary space - The
nums
list storeskΒ²
elements for each submatrix - The sorting operation may use additional
O(kΒ²)
space depending on the implementation - The dominant auxiliary space is
O(kΒ²)
for storing the submatrix elements
Learn more about how to find time and space complexity quickly.
Common Pitfalls
Pitfall 1: Misunderstanding the "Distinct Values" Requirement
The Problem: A common mistake is calculating the minimum difference between ALL pairs of elements in the submatrix, including pairs with identical values. This would always return 0 when duplicate values exist in the submatrix.
Incorrect Implementation:
# WRONG: This includes differences between identical values
min_difference = min(abs(a - b) for a, b in pairwise(subgrid_values))
# This would always be 0 if any consecutive elements after sorting are the same
Correct Implementation:
# CORRECT: Only consider pairs with distinct values
min_difference = min(
(abs(a - b) for a, b in pairwise(subgrid_values) if a != b),
default=0
)
Pitfall 2: Inefficient Duplicate Pair Checking
The Problem: Some might try to check all possible pairs (not just consecutive ones after sorting) or use nested loops to find distinct pairs, leading to unnecessary complexity.
Inefficient Approach:
# INEFFICIENT: Checking all O(k^4) pairs
min_diff = float('inf')
for i in range(len(subgrid_values)):
for j in range(i + 1, len(subgrid_values)):
if subgrid_values[i] != subgrid_values[j]:
min_diff = min(min_diff, abs(subgrid_values[i] - subgrid_values[j]))
Optimal Solution: After sorting, the minimum difference between distinct values must occur between consecutive elements in the sorted array. This reduces the problem from O(k^4) comparisons to O(k^2) comparisons.
Pitfall 3: Incorrect Handling of All-Identical Submatrices
The Problem: When all elements in a submatrix are identical, there are no distinct pairs. The code might crash or return an incorrect value if this edge case isn't handled properly.
Problematic Code:
# WRONG: This would raise ValueError if no distinct pairs exist
min_difference = min(abs(a - b) for a, b in pairwise(subgrid_values) if a != b)
Correct Handling:
# CORRECT: Use default=0 to handle the case when all elements are identical
min_difference = min(
(abs(a - b) for a, b in pairwise(subgrid_values) if a != b),
default=0
)
Pitfall 4: Off-by-One Errors in Submatrix Boundaries
The Problem: Incorrectly calculating the range of valid starting positions or the boundaries of each submatrix.
Common Mistakes:
# WRONG: This would go out of bounds
for i in range(m - k + 2): # Should be m - k + 1
for j in range(n - k + 2): # Should be n - k + 1
# WRONG: Incorrect submatrix extraction
for x in range(i, i + k - 1): # Should be i + k
for y in range(j, j + k - 1): # Should be j + k
Correct Implementation:
# Valid starting positions
for i in range(m - k + 1):
for j in range(n - k + 1):
# Extract kΓk submatrix
for x in range(i, i + k):
for y in range(j, j + k):
subgrid_values.append(grid[x][y])
What is the best way of checking if an element exists in a sorted array once in terms of time complexity? Select the best that applies.
Recommended Readings
Sorting Summary Comparisons We presented quite a few sorting algorithms and it is essential to know the advantages and disadvantages of each one The basic algorithms are easy to visualize and easy to learn for beginner programmers because of their simplicity As such they will suffice if you don't know any advanced
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Donβt Miss This!