Facebook Pixel

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:

  1. Find all pairs of distinct values within that submatrix
  2. Calculate the absolute difference for each pair
  3. 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.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

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:

  1. For each k x k submatrix, extract all its elements
  2. Sort these elements
  3. Check only consecutive pairs in the sorted list (using pairwise)
  4. Skip pairs where both elements are the same (we need distinct values)
  5. 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 Evaluator

Example 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 takes O(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 uses O((m - k + 1) Γ— (n - k + 1)) space, but this is the output and typically not counted in auxiliary space
  • The nums list stores kΒ² 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])
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

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

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More