2711. Difference of Number of Distinct Values on Diagonals
Problem Description
You are given a 2D grid of size m x n containing integer values. Your task is to create a new matrix called answer of the same size where each cell contains a calculated value based on diagonal elements.
For each cell grid[r][c], you need to:
- 
Count distinct values on the top-left diagonal: Look at all cells that lie on the same diagonal line going towards the top-left direction from
grid[r][c]. Count how many distinct values appear on this diagonal, excludinggrid[r][c]itself. Call this countleftAbove[r][c]. - 
Count distinct values on the bottom-right diagonal: Look at all cells that lie on the same diagonal line going towards the bottom-right direction from
grid[r][c]. Count how many distinct values appear on this diagonal, excludinggrid[r][c]itself. Call this countrightBelow[r][c]. - 
Calculate the answer: The value at
answer[r][c]is the absolute difference between these two counts:|leftAbove[r][c] - rightBelow[r][c]|. 
A diagonal line in the matrix starts from either the topmost row or the leftmost column and extends in the bottom-right direction until it reaches the boundary of the matrix.
For example, if you're at position (2, 3):
- The top-left diagonal would include cells at positions like 
(1, 2),(0, 1)(if they exist) - The bottom-right diagonal would include cells at positions like 
(3, 4),(4, 5)(if they exist) 
The solution iterates through each cell in the grid. For each cell (i, j), it:
- Traverses diagonally up-left to collect all values and counts distinct ones
 - Traverses diagonally down-right to collect all values and counts distinct ones
 - Calculates the absolute difference between these two counts
 - Stores this difference in the corresponding position of the answer matrix
 
Intuition
The problem asks us to examine diagonal patterns for each cell, which immediately suggests we need to traverse diagonals in two directions from each position.
The key insight is that for any cell (i, j), the cells on its diagonal follow a simple pattern:
- Moving up-left means decreasing both row and column indices by 1: 
(i-1, j-1),(i-2, j-2), etc. - Moving down-right means increasing both row and column indices by 1: 
(i+1, j+1),(i+2, j+2), etc. 
Since we need to count distinct values along each diagonal direction, using a set data structure is natural - it automatically handles duplicates for us. We can traverse in each direction, add values to a set, and the size of the set gives us the count of distinct values.
The straightforward approach is to:
- For each cell in the grid, treat it as our reference point
 - Walk diagonally up-left from 
(i, j)by repeatedly doingx = x - 1, y = y - 1until we hit the grid boundary (when eitherxbecomes 0 orybecomes 0) - Collect all values encountered in a set to get the distinct count
 - Similarly, walk diagonally down-right from 
(i, j)by repeatedly doingx = x + 1, y = y + 1until we hit the grid boundary (when eitherxreachesm-1oryreachesn-1) - The absolute difference between these two counts gives us our answer for that cell
 
This direct simulation approach works well because we're simply implementing exactly what the problem describes - no need for complex preprocessing or optimization. The use of sets naturally handles the "distinct values" requirement, and the diagonal traversal is straightforward with coordinate manipulation.
Solution Approach
The solution implements a direct simulation approach by iterating through each cell in the grid and calculating the required values for that position.
Main Algorithm Structure:
- 
Initialize the result matrix: Create an
m x nmatrixansfilled with zeros to store our answers. - 
Iterate through each cell: Use nested loops to visit each cell
(i, j)in the grid. - 
Count distinct values on the top-left diagonal:
- Start from the current position 
(i, j)by settingx = i, y = j - Create an empty set 
sto track distinct values - Move diagonally up-left using a while loop: 
while x and y:- First move one step: 
x = x - 1, y = y - 1 - Add the value at this new position to the set: 
s.add(grid[x][y]) 
 - First move one step: 
 - The loop continues while both 
x > 0andy > 0(sincex and yevaluates toTrueonly when both are non-zero) - Store the count of distinct values: 
tl = len(s) 
 - Start from the current position 
 - 
Count distinct values on the bottom-right diagonal:
- Reset to the current position: 
x = i, y = j - Create a new empty set 
s - Move diagonally down-right using a while loop: 
while x + 1 < m and y + 1 < n:- First move one step: 
x = x + 1, y = y + 1 - Add the value at this new position to the set: 
s.add(grid[x][y]) 
 - First move one step: 
 - The loop continues while we can move without going out of bounds
 - Store the count of distinct values: 
br = len(s) 
 - Reset to the current position: 
 - 
Calculate and store the result:
- Compute the absolute difference: 
ans[i][j] = abs(tl - br) 
 - Compute the absolute difference: 
 
Key Implementation Details:
- 
The boundary checking is crucial: for the top-left diagonal, we stop when either index would become negative. For the bottom-right diagonal, we check that the next position would still be within bounds before moving.
 - 
Sets are used for automatic deduplication - when we add a value that already exists in the set, the set size doesn't increase, giving us the correct count of distinct values.
 - 
The movement pattern
(x-1, y-1)for up-left and(x+1, y+1)for down-right ensures we stay on the same diagonal line throughout the traversal. 
Time Complexity: O(m * n * min(m, n)) where the third factor comes from the diagonal traversal which can be at most min(m, n) cells long.
Space Complexity: O(min(m, n)) for the sets used to track distinct values, plus O(m * n) for the answer matrix.
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 small example to illustrate the solution approach.
Consider a 3x4 grid:
grid = [[1, 2, 3, 4], [5, 1, 2, 3], [6, 5, 1, 2]]
Let's calculate the value for cell (1, 2) which contains the value 2:
Step 1: Count distinct values on the top-left diagonal
- Start at position 
(1, 2)withx = 1, y = 2 - Create empty set 
s = {} - Move diagonally up-left:
- First iteration: 
x = 0, y = 1, addgrid[0][1] = 2to set →s = {2} - Second iteration would make 
x = -1, so we stop (out of bounds) 
 - First iteration: 
 - Count of distinct values: 
tl = len({2}) = 1 
Step 2: Count distinct values on the bottom-right diagonal
- Reset to position 
(1, 2)withx = 1, y = 2 - Create new empty set 
s = {} - Move diagonally down-right:
- First iteration: Check if 
x + 1 < 3andy + 1 < 4→ both true - Move to 
x = 2, y = 3, addgrid[2][3] = 2to set →s = {2} - Second iteration would make 
y = 4, which is out of bounds, so we stop 
 - First iteration: Check if 
 - Count of distinct values: 
br = len({2}) = 1 
Step 3: Calculate the answer
answer[1][2] = |tl - br| = |1 - 1| = 0
Let's do one more calculation for cell (0, 0) which contains value 1:
Top-left diagonal:
- Start at 
(0, 0) - Can't move up-left (already at top-left corner)
 tl = 0(no values found)
Bottom-right diagonal:
- Start at 
(0, 0) - Move to 
(1, 1)→ addgrid[1][1] = 1→s = {1} - Move to 
(2, 2)→ addgrid[2][2] = 1→s = {1}(still just one distinct value) - Can't move further (would go out of bounds)
 br = len({1}) = 1
Result: answer[0][0] = |0 - 1| = 1
The complete answer matrix would be:
answer = [[1, 0, 0, 1], [1, 0, 0, 0], [1, 0, 0, 0]]
This example demonstrates how the algorithm traverses diagonals in both directions, uses sets to track distinct values, and calculates the absolute difference for each cell.
Solution Implementation
1class Solution:
2    def differenceOfDistinctValues(self, grid: List[List[int]]) -> List[List[int]]:
3        """
4        Calculate the absolute difference between distinct values in top-left and bottom-right diagonals
5        for each cell in the grid.
6      
7        Args:
8            grid: 2D list of integers
9          
10        Returns:
11            2D list where each cell contains the absolute difference of distinct values
12            in its top-left and bottom-right diagonals
13        """
14        rows, cols = len(grid), len(grid[0])
15        result = [[0] * cols for _ in range(rows)]
16      
17        # Process each cell in the grid
18        for row in range(rows):
19            for col in range(cols):
20                # Count distinct values in top-left diagonal
21                curr_row, curr_col = row, col
22                top_left_values = set()
23              
24                # Move diagonally up-left and collect values
25                while curr_row > 0 and curr_col > 0:
26                    curr_row -= 1
27                    curr_col -= 1
28                    top_left_values.add(grid[curr_row][curr_col])
29              
30                top_left_count = len(top_left_values)
31              
32                # Count distinct values in bottom-right diagonal
33                curr_row, curr_col = row, col
34                bottom_right_values = set()
35              
36                # Move diagonally down-right and collect values
37                while curr_row + 1 < rows and curr_col + 1 < cols:
38                    curr_row += 1
39                    curr_col += 1
40                    bottom_right_values.add(grid[curr_row][curr_col])
41              
42                bottom_right_count = len(bottom_right_values)
43              
44                # Store the absolute difference
45                result[row][col] = abs(top_left_count - bottom_right_count)
46      
47        return result
481class Solution {
2    public int[][] differenceOfDistinctValues(int[][] grid) {
3        // Get dimensions of the grid
4        int rows = grid.length;
5        int cols = grid[0].length;
6      
7        // Initialize result matrix with same dimensions
8        int[][] result = new int[rows][cols];
9      
10        // Iterate through each cell in the grid
11        for (int row = 0; row < rows; row++) {
12            for (int col = 0; col < cols; col++) {
13                // Calculate distinct values in top-left diagonal
14                int currentRow = row;
15                int currentCol = col;
16                Set<Integer> topLeftValues = new HashSet<>();
17              
18                // Move diagonally up-left and collect distinct values
19                while (currentRow > 0 && currentCol > 0) {
20                    currentRow--;
21                    currentCol--;
22                    topLeftValues.add(grid[currentRow][currentCol]);
23                }
24                int topLeftCount = topLeftValues.size();
25              
26                // Calculate distinct values in bottom-right diagonal
27                currentRow = row;
28                currentCol = col;
29                Set<Integer> bottomRightValues = new HashSet<>();
30              
31                // Move diagonally down-right and collect distinct values
32                while (currentRow < rows - 1 && currentCol < cols - 1) {
33                    currentRow++;
34                    currentCol++;
35                    bottomRightValues.add(grid[currentRow][currentCol]);
36                }
37                int bottomRightCount = bottomRightValues.size();
38              
39                // Store the absolute difference in the result matrix
40                result[row][col] = Math.abs(topLeftCount - bottomRightCount);
41            }
42        }
43      
44        return result;
45    }
46}
471class Solution {
2public:
3    vector<vector<int>> differenceOfDistinctValues(vector<vector<int>>& grid) {
4        int rows = grid.size();
5        int cols = grid[0].size();
6      
7        // Initialize result matrix with same dimensions as input grid
8        vector<vector<int>> result(rows, vector<int>(cols));
9      
10        // Process each cell in the grid
11        for (int row = 0; row < rows; ++row) {
12            for (int col = 0; col < cols; ++col) {
13                // Count distinct values in top-left diagonal
14                int currentRow = row;
15                int currentCol = col;
16                unordered_set<int> distinctValues;
17              
18                // Move diagonally up-left and collect distinct values
19                while (currentRow > 0 && currentCol > 0) {
20                    distinctValues.insert(grid[--currentRow][--currentCol]);
21                }
22                int topLeftCount = distinctValues.size();
23              
24                // Reset position and clear set for bottom-right diagonal
25                currentRow = row;
26                currentCol = col;
27                distinctValues.clear();
28              
29                // Move diagonally down-right and collect distinct values
30                while (currentRow < rows - 1 && currentCol < cols - 1) {
31                    distinctValues.insert(grid[++currentRow][++currentCol]);
32                }
33                int bottomRightCount = distinctValues.size();
34              
35                // Store absolute difference of distinct counts
36                result[row][col] = abs(topLeftCount - bottomRightCount);
37            }
38        }
39      
40        return result;
41    }
42};
431/**
2 * Calculates the absolute difference between distinct values in top-left and bottom-right diagonals
3 * for each cell in the grid
4 * @param grid - 2D array of numbers
5 * @returns 2D array where each cell contains the absolute difference of distinct values
6 */
7function differenceOfDistinctValues(grid: number[][]): number[][] {
8    const rows: number = grid.length;
9    const cols: number = grid[0].length;
10  
11    // Initialize result matrix with zeros
12    const result: number[][] = Array(rows)
13        .fill(0)
14        .map(() => Array(cols).fill(0));
15  
16    // Process each cell in the grid
17    for (let row = 0; row < rows; ++row) {
18        for (let col = 0; col < cols; ++col) {
19            // Count distinct values in top-left diagonal
20            let currentRow: number = row;
21            let currentCol: number = col;
22            const topLeftSet = new Set<number>();
23          
24            // Move diagonally up-left and collect values
25            while (currentRow > 0 && currentCol > 0) {
26                currentRow--;
27                currentCol--;
28                topLeftSet.add(grid[currentRow][currentCol]);
29            }
30            const topLeftCount: number = topLeftSet.size;
31          
32            // Count distinct values in bottom-right diagonal
33            currentRow = row;
34            currentCol = col;
35            const bottomRightSet = new Set<number>();
36          
37            // Move diagonally down-right and collect values
38            while (currentRow + 1 < rows && currentCol + 1 < cols) {
39                currentRow++;
40                currentCol++;
41                bottomRightSet.add(grid[currentRow][currentCol]);
42            }
43            const bottomRightCount: number = bottomRightSet.size;
44          
45            // Calculate and store the absolute difference
46            result[row][col] = Math.abs(topLeftCount - bottomRightCount);
47        }
48    }
49  
50    return result;
51}
52Time and Space Complexity
Time Complexity: O(m × n × min(m, n))
The code iterates through each cell in the grid using two nested loops, which gives us O(m × n) iterations. For each cell (i, j), it performs two diagonal traversals:
- One traversal going up-left from 
(i, j)to collect distinct values - One traversal going down-right from 
(i, j)to collect distinct values 
Each diagonal traversal can go at most min(m, n) steps since a diagonal is bounded by the smaller dimension of the grid. Although each traversal uses a set to track distinct values (with O(1) average case for add operations), the traversal itself takes O(min(m, n)) time.
Therefore, the total time complexity is O(m × n × min(m, n)).
Space Complexity: O(m × n)
The space complexity consists of:
- The output array 
answhich is am × nmatrix:O(m × n) - The temporary set 
sused for storing distinct values during diagonal traversals:O(min(m, n))in the worst case when all diagonal elements are distinct - Other variables like 
x,y,tl,br:O(1) 
Since O(m × n) dominates O(min(m, n)), the overall space complexity is O(m × n).
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Off-by-One Error in Diagonal Traversal
A common mistake is incorrectly handling the boundary conditions or including the current cell in the diagonal counts. The problem explicitly states to exclude grid[r][c] itself when counting distinct values.
Incorrect Implementation:
# Wrong: This includes the current cell in the count while curr_row >= 0 and curr_col >= 0: top_left_values.add(grid[curr_row][curr_col]) curr_row -= 1 curr_col -= 1
Correct Implementation:
# Right: Move first, then add to set (excludes current cell) while curr_row > 0 and curr_col > 0: curr_row -= 1 curr_col -= 1 top_left_values.add(grid[curr_row][curr_col])
2. Reusing the Same Set for Both Diagonals
Another pitfall is trying to optimize by reusing the same set, which leads to incorrect counts since the set would contain values from both diagonals.
Incorrect Implementation:
distinct_values = set()
# Count top-left diagonal
while curr_row > 0 and curr_col > 0:
    curr_row -= 1
    curr_col -= 1
    distinct_values.add(grid[curr_row][curr_col])
top_left_count = len(distinct_values)
# Wrong: Set still contains values from top-left diagonal
curr_row, curr_col = row, col
while curr_row + 1 < rows and curr_col + 1 < cols:
    curr_row += 1
    curr_col += 1
    distinct_values.add(grid[curr_row][curr_col])
bottom_right_count = len(distinct_values) - top_left_count  # This is incorrect!
Correct Implementation:
# Create separate sets for each diagonal
top_left_values = set()
# ... collect top-left values ...
bottom_right_values = set()  # New set for bottom-right
# ... collect bottom-right values ...
3. Incorrect Boundary Checking Logic
Using the wrong comparison operators or checking conditions after moving can cause index out of bounds errors.
Incorrect Implementation:
# Wrong: This could cause index out of bounds while curr_row >= 0 and curr_col >= 0: curr_row -= 1 curr_col -= 1 if curr_row >= 0 and curr_col >= 0: # Additional check needed top_left_values.add(grid[curr_row][curr_col])
Correct Implementation:
# Right: Check before moving ensures we never go out of bounds while curr_row > 0 and curr_col > 0: curr_row -= 1 curr_col -= 1 top_left_values.add(grid[curr_row][curr_col])
4. Forgetting to Reset Position Variables
When transitioning from counting the top-left diagonal to the bottom-right diagonal, forgetting to reset the position variables will start the second traversal from the wrong position.
Incorrect Implementation:
curr_row, curr_col = row, col # Count top-left diagonal while curr_row > 0 and curr_col > 0: curr_row -= 1 curr_col -= 1 top_left_values.add(grid[curr_row][curr_col]) # Wrong: curr_row and curr_col are now at the end of top-left diagonal # not at the original (row, col) position while curr_row + 1 < rows and curr_col + 1 < cols: curr_row += 1 curr_col += 1 bottom_right_values.add(grid[curr_row][curr_col])
Correct Implementation:
# Reset position for bottom-right diagonal traversal
curr_row, curr_col = row, col
bottom_right_values = set()
while curr_row + 1 < rows and curr_col + 1 < cols:
    curr_row += 1
    curr_col += 1
    bottom_right_values.add(grid[curr_row][curr_col])
A heap is a ...?
Recommended Readings
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 If you prefer videos here's a video that explains recursion in a fun and easy way 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 him
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!