Facebook Pixel

3030. Find the Grid of Region Average

MediumArrayMatrix
Leetcode Link

Problem Description

You're given a grayscale image represented as an m x n grid where each cell image[i][j] contains a pixel intensity value between 0 and 255. You also have a non-negative integer threshold.

The task is to identify valid "regions" and calculate a result grid based on these regions.

What is a region?

  • A region is a 3 x 3 subgrid from the image
  • For a 3 x 3 subgrid to be a valid region, the absolute difference between any two adjacent pixels within it must be less than or equal to threshold
  • Two pixels are adjacent if they share an edge (horizontally or vertically connected, not diagonally)

Key rules:

  • A single pixel can belong to multiple overlapping regions
  • Each pixel in a valid region belongs to that region

How to calculate the result: For each pixel [i][j] in the result grid:

  1. If the pixel belongs to one or more regions:

    • Calculate the average intensity of each region it belongs to (rounded down)
    • Take the average of all these rounded-down averages
    • Round down this final average to get result[i][j]
  2. If the pixel doesn't belong to any region:

    • result[i][j] = image[i][j] (keep the original value)

Example of checking adjacency in a 3x3 region: In a 3 x 3 subgrid, you need to check:

  • Horizontal adjacencies: 6 pairs (2 pairs in each of the 3 rows)
  • Vertical adjacencies: 6 pairs (2 pairs in each of the 3 columns)
  • Total: 12 adjacent pairs to verify

The solution iterates through all possible 3 x 3 subgrids, validates them as regions, tracks how many regions each pixel belongs to, and accumulates the sum of average intensities to finally compute the required result grid.

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

Intuition

The key insight is that we need to handle overlapping regions and track which pixels belong to which valid regions. Since a pixel can belong to multiple 3 x 3 regions, we can't just process regions independently - we need to accumulate information.

Think about it this way: if we stand at any pixel position, it could potentially be part of up to 9 different 3 x 3 regions (when it's far enough from the borders). Each of these regions might or might not be valid based on the threshold condition.

The natural approach is to:

  1. Check every possible 3 x 3 subgrid in the image
  2. For each subgrid, verify if it forms a valid region by checking all adjacent pixel pairs
  3. Keep track of contributions to each pixel

To implement this efficiently, we use two auxiliary grids:

  • ans[i][j]: accumulates the sum of all region averages that pixel (i,j) belongs to
  • ct[i][j]: counts how many valid regions pixel (i,j) belongs to

Why accumulate sums instead of storing individual averages? Because if a pixel belongs to multiple regions, we need to average the averages. By accumulating (sum of region) // 9 for each region and counting occurrences, we can compute the final average as accumulated_sum / count at the end.

The adjacency checking is straightforward but tedious - for each 3 x 3 subgrid, we check:

  • All horizontal adjacencies: compare each pixel with its right neighbor (except the rightmost column)
  • All vertical adjacencies: compare each pixel with its bottom neighbor (except the bottom row)

If all adjacency checks pass (absolute difference ≤ threshold), we mark it as a valid region and update our accumulation arrays for all 9 pixels in that region.

Finally, we construct the result: if a pixel belongs to no regions (ct[i][j] == 0), keep the original value; otherwise, divide the accumulated sum by the count to get the average of averages.

Solution Approach

The implementation uses a systematic approach to check all possible 3 x 3 regions and accumulate results:

1. Initialize tracking arrays:

  • ans: An n x m grid to accumulate the sum of region averages for each pixel
  • ct: An n x m grid to count how many valid regions each pixel belongs to

2. Iterate through all possible 3 x 3 subgrids: For each top-left corner at position (i, j) where i ranges from 0 to n-3 and j ranges from 0 to m-3:

3. Validate the region: Check all adjacent pairs within the 3 x 3 subgrid:

  • Horizontal adjacencies: For each of the 3 rows, check 2 consecutive pairs:
    for k in range(3):  # rows
        for l in range(2):  # columns (0-1, 1-2)
            check |image[i+k][j+l] - image[i+k][j+l+1]| <= threshold
  • Vertical adjacencies: For each of the 3 columns, check 2 consecutive pairs:
    for k in range(2):  # rows (0-1, 1-2)
        for l in range(3):  # columns
            check |image[i+k][j+l] - image[i+k+1][j+l]| <= threshold

4. Process valid regions: If all adjacency checks pass (region remains True):

  • Calculate the sum of all 9 pixels in the region: tot = sum of all pixels in 3x3 subgrid
  • For each of the 9 pixels in this region:
    • Increment its counter: ct[i+k][j+l] += 1
    • Add the region's average (rounded down) to its accumulator: ans[i+k][j+l] += tot // 9

5. Calculate final results: For each pixel (i, j) in the grid:

  • If ct[i][j] == 0: The pixel doesn't belong to any region, so ans[i][j] = image[i][j]
  • Otherwise: Calculate the average of averages by dividing the accumulated sum by the count: ans[i][j] //= ct[i][j]

Time Complexity: O(n * m) where we iterate through each possible 3 x 3 subgrid and perform constant work for validation and accumulation.

Space Complexity: O(n * m) for the two auxiliary arrays ans and ct.

The key pattern here is the accumulation technique - instead of storing lists of regions for each pixel, we maintain running sums and counts, which allows us to efficiently compute the final averages without additional storage overhead.

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 small example with a 4 x 4 image and threshold = 2:

image = [[1, 2, 3, 4],
         [2, 3, 4, 5],
         [3, 4, 5, 6],
         [4, 5, 6, 7]]

threshold = 2

Step 1: Initialize tracking arrays

ans = [[0, 0, 0, 0],    ct = [[0, 0, 0, 0],
       [0, 0, 0, 0],          [0, 0, 0, 0],
       [0, 0, 0, 0],          [0, 0, 0, 0],
       [0, 0, 0, 0]]          [0, 0, 0, 0]]

Step 2: Check all possible 3x3 subgrids

We have 2 possible 3x3 regions (top-left corners at (0,0) and (0,1), (1,0) and (1,1)).

Region 1: Top-left at (0,0)

Subgrid: [[1, 2, 3],
          [2, 3, 4],
          [3, 4, 5]]

Check adjacencies:

  • Horizontal: |1-2|=1≤2 ✓, |2-3|=1≤2 ✓, |2-3|=1≤2 ✓, |3-4|=1≤2 ✓, |3-4|=1≤2 ✓, |4-5|=1≤2 ✓
  • Vertical: |1-2|=1≤2 ✓, |2-3|=1≤2 ✓, |2-3|=1≤2 ✓, |3-4|=1≤2 ✓, |3-4|=1≤2 ✓, |4-5|=1≤2 ✓

All checks pass! This is a valid region.

  • Sum = 1+2+3+2+3+4+3+4+5 = 27
  • Average = 27 // 9 = 3

Update ans and ct for all 9 pixels in this region:

ans = [[3, 3, 3, 0],    ct = [[1, 1, 1, 0],
       [3, 3, 3, 0],          [1, 1, 1, 0],
       [3, 3, 3, 0],          [1, 1, 1, 0],
       [0, 0, 0, 0]]          [0, 0, 0, 0]]

Region 2: Top-left at (0,1)

Subgrid: [[2, 3, 4],
          [3, 4, 5],
          [4, 5, 6]]

Following same validation (all adjacencies ≤2), this is valid.

  • Sum = 2+3+4+3+4+5+4+5+6 = 36
  • Average = 36 // 9 = 4

Update (accumulate) for these 9 pixels:

ans = [[3, 7, 7, 4],    ct = [[1, 2, 2, 1],
       [3, 7, 7, 4],          [1, 2, 2, 1],
       [3, 7, 7, 4],          [1, 2, 2, 1],
       [0, 0, 0, 0]]          [0, 0, 0, 0]]

Continue for remaining regions at (1,0) and (1,1)...

After checking all regions, let's say we end up with:

ans = [[3, 7, 7, 4],    ct = [[1, 2, 2, 1],
       [7, 14, 14, 7],        [2, 4, 4, 2],
       [7, 14, 14, 7],        [2, 4, 4, 2],
       [4, 7, 7, 4]]          [1, 2, 2, 1]]

Step 3: Calculate final result

For each pixel (i,j):

  • If ct[i][j] > 0: result[i][j] = ans[i][j] // ct[i][j]
  • If ct[i][j] == 0: result[i][j] = image[i][j]
result = [[3//1, 7//2, 7//2, 4//1],
          [7//2, 14//4, 14//4, 7//2],
          [7//2, 14//4, 14//4, 7//2],
          [4//1, 7//2, 7//2, 4//1]]

       = [[3, 3, 3, 4],
          [3, 3, 3, 3],
          [3, 3, 3, 3],
          [4, 3, 3, 4]]

The pixels in the center belong to more regions and thus have their values smoothed by averaging multiple region averages. Corner pixels belong to fewer regions, maintaining values closer to the original.

Solution Implementation

1class Solution:
2    def resultGrid(self, image: List[List[int]], threshold: int) -> List[List[int]]:
3        # Get dimensions of the image
4        rows, cols = len(image), len(image[0])
5      
6        # Initialize result grid and count grid
7        # result_sum will accumulate sums for each cell
8        # count tracks how many valid regions include each cell
9        result_sum = [[0] * cols for _ in range(rows)]
10        count = [[0] * cols for _ in range(rows)]
11      
12        # Iterate through all possible 3x3 regions in the image
13        for start_row in range(rows - 2):
14            for start_col in range(cols - 2):
15                # Check if current 3x3 region is valid
16                is_valid_region = True
17              
18                # Check horizontal adjacency constraints
19                # For each row in the 3x3 region, check adjacent horizontal cells
20                for row_offset in range(3):
21                    for col_offset in range(2):
22                        current_val = image[start_row + row_offset][start_col + col_offset]
23                        right_neighbor = image[start_row + row_offset][start_col + col_offset + 1]
24                        is_valid_region &= abs(current_val - right_neighbor) <= threshold
25              
26                # Check vertical adjacency constraints
27                # For each column in the 3x3 region, check adjacent vertical cells
28                for row_offset in range(2):
29                    for col_offset in range(3):
30                        current_val = image[start_row + row_offset][start_col + col_offset]
31                        bottom_neighbor = image[start_row + row_offset + 1][start_col + col_offset]
32                        is_valid_region &= abs(current_val - bottom_neighbor) <= threshold
33              
34                # If region is valid, calculate average and update cells
35                if is_valid_region:
36                    # Calculate sum of all values in the 3x3 region
37                    region_sum = 0
38                    for row_offset in range(3):
39                        for col_offset in range(3):
40                            region_sum += image[start_row + row_offset][start_col + col_offset]
41                  
42                    # Update each cell in the region with the average value
43                    region_average = region_sum // 9
44                    for row_offset in range(3):
45                        for col_offset in range(3):
46                            count[start_row + row_offset][start_col + col_offset] += 1
47                            result_sum[start_row + row_offset][start_col + col_offset] += region_average
48      
49        # Finalize the result grid
50        result = [[0] * cols for _ in range(rows)]
51        for row in range(rows):
52            for col in range(cols):
53                if count[row][col] == 0:
54                    # Cell is not part of any valid region, keep original value
55                    result[row][col] = image[row][col]
56                else:
57                    # Cell is part of valid regions, calculate average of all region averages
58                    result[row][col] = result_sum[row][col] // count[row][col]
59      
60        return result
61
1class Solution {
2    public int[][] resultGrid(int[][] image, int threshold) {
3        int rows = image.length;
4        int cols = image[0].length;
5      
6        // Store the sum of region averages for each cell
7        int[][] sumOfAverages = new int[rows][cols];
8        // Store the count of valid regions each cell belongs to
9        int[][] regionCount = new int[rows][cols];
10      
11        // Iterate through all possible 3x3 regions in the image
12        for (int startRow = 0; startRow + 2 < rows; startRow++) {
13            for (int startCol = 0; startCol + 2 < cols; startCol++) {
14              
15                // Check if current 3x3 region is valid
16                boolean isValidRegion = true;
17              
18                // Check horizontal adjacency differences within the 3x3 region
19                for (int row = 0; row < 3; row++) {
20                    for (int col = 0; col < 2; col++) {
21                        int currentPixel = image[startRow + row][startCol + col];
22                        int rightPixel = image[startRow + row][startCol + col + 1];
23                        isValidRegion &= Math.abs(currentPixel - rightPixel) <= threshold;
24                    }
25                }
26              
27                // Check vertical adjacency differences within the 3x3 region
28                for (int row = 0; row < 2; row++) {
29                    for (int col = 0; col < 3; col++) {
30                        int currentPixel = image[startRow + row][startCol + col];
31                        int belowPixel = image[startRow + row + 1][startCol + col];
32                        isValidRegion &= Math.abs(currentPixel - belowPixel) <= threshold;
33                    }
34                }
35              
36                // If region is valid, calculate average and update cells
37                if (isValidRegion) {
38                    // Calculate sum of all pixels in the 3x3 region
39                    int regionSum = 0;
40                    for (int row = 0; row < 3; row++) {
41                        for (int col = 0; col < 3; col++) {
42                            regionSum += image[startRow + row][startCol + col];
43                        }
44                    }
45                  
46                    // Calculate average (integer division)
47                    int regionAverage = regionSum / 9;
48                  
49                    // Update each cell in the region with the average
50                    for (int row = 0; row < 3; row++) {
51                        for (int col = 0; col < 3; col++) {
52                            regionCount[startRow + row][startCol + col]++;
53                            sumOfAverages[startRow + row][startCol + col] += regionAverage;
54                        }
55                    }
56                }
57            }
58        }
59      
60        // Calculate final result for each cell
61        for (int i = 0; i < rows; i++) {
62            for (int j = 0; j < cols; j++) {
63                if (regionCount[i][j] == 0) {
64                    // Cell doesn't belong to any valid region, keep original value
65                    sumOfAverages[i][j] = image[i][j];
66                } else {
67                    // Cell belongs to valid regions, calculate average of averages
68                    sumOfAverages[i][j] /= regionCount[i][j];
69                }
70            }
71        }
72      
73        return sumOfAverages;
74    }
75}
76
1class Solution {
2public:
3    vector<vector<int>> resultGrid(vector<vector<int>>& image, int threshold) {
4        int rows = image.size();
5        int cols = image[0].size();
6      
7        // Initialize result grid and count grid
8        // result[i][j] will store sum of averages from all valid regions containing (i,j)
9        // count[i][j] will store number of valid regions containing (i,j)
10        vector<vector<int>> result(rows, vector<int>(cols, 0));
11        vector<vector<int>> count(rows, vector<int>(cols, 0));
12      
13        // Iterate through all possible 3x3 regions
14        for (int topRow = 0; topRow <= rows - 3; ++topRow) {
15            for (int leftCol = 0; leftCol <= cols - 3; ++leftCol) {
16              
17                // Check if current 3x3 region is valid
18                bool isValidRegion = true;
19              
20                // Check horizontal adjacency constraints
21                // For each row in the 3x3 region, check adjacent horizontal cells
22                for (int row = 0; row < 3; ++row) {
23                    for (int col = 0; col < 2; ++col) {
24                        int diff = abs(image[topRow + row][leftCol + col] - 
25                                     image[topRow + row][leftCol + col + 1]);
26                        if (diff > threshold) {
27                            isValidRegion = false;
28                        }
29                    }
30                }
31              
32                // Check vertical adjacency constraints
33                // For each column in the 3x3 region, check adjacent vertical cells
34                for (int row = 0; row < 2; ++row) {
35                    for (int col = 0; col < 3; ++col) {
36                        int diff = abs(image[topRow + row][leftCol + col] - 
37                                     image[topRow + row + 1][leftCol + col]);
38                        if (diff > threshold) {
39                            isValidRegion = false;
40                        }
41                    }
42                }
43              
44                // If region is valid, calculate average and update cells
45                if (isValidRegion) {
46                    // Calculate sum of all 9 cells in the region
47                    int sum = 0;
48                    for (int row = 0; row < 3; ++row) {
49                        for (int col = 0; col < 3; ++col) {
50                            sum += image[topRow + row][leftCol + col];
51                        }
52                    }
53                  
54                    // Calculate average (integer division)
55                    int average = sum / 9;
56                  
57                    // Update each cell in the region with the average
58                    for (int row = 0; row < 3; ++row) {
59                        for (int col = 0; col < 3; ++col) {
60                            count[topRow + row][leftCol + col]++;
61                            result[topRow + row][leftCol + col] += average;
62                        }
63                    }
64                }
65            }
66        }
67      
68        // Finalize the result grid
69        for (int i = 0; i < rows; ++i) {
70            for (int j = 0; j < cols; ++j) {
71                if (count[i][j] == 0) {
72                    // Cell not part of any valid region, keep original value
73                    result[i][j] = image[i][j];
74                } else {
75                    // Cell part of one or more valid regions, take average
76                    result[i][j] /= count[i][j];
77                }
78            }
79        }
80      
81        return result;
82    }
83};
84
1/**
2 * Processes an image grid to create regions and average their values based on a threshold
3 * @param image - 2D array representing the image pixels
4 * @param threshold - Maximum allowed difference between adjacent pixels in a valid region
5 * @returns Modified image grid with averaged values for valid regions
6 */
7function resultGrid(image: number[][], threshold: number): number[][] {
8    const rows: number = image.length;
9    const cols: number = image[0].length;
10  
11    // Initialize result grid and count grid to track overlapping regions
12    const result: number[][] = Array.from({ length: rows }, () => new Array(cols).fill(0));
13    const regionCount: number[][] = Array.from({ length: rows }, () => new Array(cols).fill(0));
14  
15    // Iterate through all possible 3x3 regions in the image
16    for (let row = 0; row + 2 < rows; row++) {
17        for (let col = 0; col + 2 < cols; col++) {
18            let isValidRegion: boolean = true;
19          
20            // Check horizontal adjacency within the 3x3 region
21            // Compare each pixel with its right neighbor
22            for (let i = 0; i < 3; i++) {
23                for (let j = 0; j < 2; j++) {
24                    const difference = Math.abs(image[row + i][col + j] - image[row + i][col + j + 1]);
25                    isValidRegion = isValidRegion && (difference <= threshold);
26                }
27            }
28          
29            // Check vertical adjacency within the 3x3 region
30            // Compare each pixel with its bottom neighbor
31            for (let i = 0; i < 2; i++) {
32                for (let j = 0; j < 3; j++) {
33                    const difference = Math.abs(image[row + i][col + j] - image[row + i + 1][col + j]);
34                    isValidRegion = isValidRegion && (difference <= threshold);
35                }
36            }
37          
38            // If region is valid, calculate average and update affected cells
39            if (isValidRegion) {
40                // Calculate sum of all pixels in the 3x3 region
41                let regionSum: number = 0;
42                for (let i = 0; i < 3; i++) {
43                    for (let j = 0; j < 3; j++) {
44                        regionSum += image[row + i][col + j];
45                    }
46                }
47              
48                // Update each cell in the region with the average value
49                const regionAverage: number = Math.floor(regionSum / 9);
50                for (let i = 0; i < 3; i++) {
51                    for (let j = 0; j < 3; j++) {
52                        regionCount[row + i][col + j]++;
53                        result[row + i][col + j] += regionAverage;
54                    }
55                }
56            }
57        }
58    }
59  
60    // Finalize the result grid
61    for (let row = 0; row < rows; row++) {
62        for (let col = 0; col < cols; col++) {
63            if (regionCount[row][col] === 0) {
64                // Cell is not part of any valid region, keep original value
65                result[row][col] = image[row][col];
66            } else {
67                // Cell is part of one or more regions, calculate final average
68                result[row][col] = Math.floor(result[row][col] / regionCount[row][col]);
69            }
70        }
71    }
72  
73    return result;
74}
75

Time and Space Complexity

Time Complexity: O(n * m) where n is the number of rows and m is the number of columns in the image.

The algorithm iterates through all possible 3x3 regions in the image:

  • The outer loops run (n-2) * (m-2) times to check each possible top-left corner of a 3x3 region
  • For each region, it performs:
    • Validation checks: 3*2 + 2*3 = 12 comparisons (constant time)
    • If valid, calculates sum: 3*3 = 9 additions (constant time)
    • Updates result and count arrays: 3*3 = 9 updates (constant time)
  • Finally, it iterates through the entire grid once more: n * m operations

Since all operations inside the loops are constant time, the overall time complexity is O((n-2) * (m-2) * 1) + O(n * m) which simplifies to O(n * m).

Space Complexity: O(n * m)

The algorithm uses:

  • ans: a 2D array of size n * m to store the accumulated sums
  • ct: a 2D array of size n * m to store the count of valid regions each cell belongs to
  • A few constant space variables (i, j, k, l, tot, region)

The total additional space used is 2 * n * m + O(1), which simplifies to O(n * m).

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Incorrect Adjacency Checking Logic

Pitfall: A common mistake is incorrectly implementing the adjacency checks, either by missing some pairs or checking diagonal adjacencies (which shouldn't be checked according to the problem).

Wrong approach:

# Incorrect: Only checking some adjacencies or including diagonals
for i in range(3):
    for j in range(3):
        if i < 2 and j < 2:  # This misses many valid adjacencies
            if abs(image[r+i][c+j] - image[r+i+1][c+j+1]) > threshold:  # Diagonal!
                is_valid = False

Correct approach:

# Check all horizontal adjacencies (6 pairs)
for row_offset in range(3):
    for col_offset in range(2):
        if abs(image[r+row_offset][c+col_offset] - image[r+row_offset][c+col_offset+1]) > threshold:
            is_valid = False

# Check all vertical adjacencies (6 pairs)
for row_offset in range(2):
    for col_offset in range(3):
        if abs(image[r+row_offset][c+col_offset] - image[r+row_offset+1][c+col_offset]) > threshold:
            is_valid = False

2. Integer Division Confusion

Pitfall: Forgetting to use integer division (//) when calculating averages, or applying rounding incorrectly. The problem specifically asks for rounding down at each step.

Wrong approach:

# Incorrect: Using float division
region_average = region_sum / 9  # Returns float
result[row][col] = result_sum[row][col] / count[row][col]  # Returns float

Correct approach:

# Always use integer division for rounding down
region_average = region_sum // 9
result[row][col] = result_sum[row][col] // count[row][col]

3. Off-by-One Errors in Boundary Conditions

Pitfall: Incorrectly setting the loop boundaries for finding 3×3 regions, which can cause index out of bounds errors.

Wrong approach:

# Incorrect: Goes out of bounds
for start_row in range(rows - 1):  # Should be rows - 2
    for start_col in range(cols - 1):  # Should be cols - 2
        # This will try to access image[rows-1+2][cols-1+2] which is out of bounds

Correct approach:

# Correct boundaries to ensure 3x3 region fits
for start_row in range(rows - 2):  # Ensures start_row + 2 < rows
    for start_col in range(cols - 2):  # Ensures start_col + 2 < cols

4. Not Handling the Case of No Valid Regions

Pitfall: Forgetting to handle pixels that don't belong to any valid region, which should retain their original values.

Wrong approach:

# Incorrect: Doesn't check if pixel belongs to any region
result[row][col] = result_sum[row][col] // count[row][col]  # Division by zero if count is 0!

Correct approach:

if count[row][col] == 0:
    # Pixel doesn't belong to any region, keep original value
    result[row][col] = image[row][col]
else:
    # Calculate average of averages
    result[row][col] = result_sum[row][col] // count[row][col]

5. Premature Optimization Breaking Logic

Pitfall: Using early termination (break) in adjacency checking without checking all pairs, which can lead to incorrect validation.

Wrong approach:

# Incorrect: Breaking early might skip necessary checks
for row_offset in range(3):
    for col_offset in range(2):
        if abs(image[r+row_offset][c+col_offset] - image[r+row_offset][c+col_offset+1]) > threshold:
            is_valid = False
            break  # This only breaks inner loop, outer loop continues!

Correct approach:

# Use a flag and check all pairs, or use proper nested break
is_valid = True
for row_offset in range(3):
    for col_offset in range(2):
        if abs(image[r+row_offset][c+col_offset] - image[r+row_offset][c+col_offset+1]) > threshold:
            is_valid = False
          
# Or use &= operator to accumulate validity
is_valid &= abs(current - neighbor) <= threshold
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

What's the output of running the following function using input 56?

1KEYBOARD = {
2    '2': 'abc',
3    '3': 'def',
4    '4': 'ghi',
5    '5': 'jkl',
6    '6': 'mno',
7    '7': 'pqrs',
8    '8': 'tuv',
9    '9': 'wxyz',
10}
11
12def letter_combinations_of_phone_number(digits):
13    def dfs(path, res):
14        if len(path) == len(digits):
15            res.append(''.join(path))
16            return
17
18        next_number = digits[len(path)]
19        for letter in KEYBOARD[next_number]:
20            path.append(letter)
21            dfs(path, res)
22            path.pop()
23
24    res = []
25    dfs([], res)
26    return res
27
1private static final Map<Character, char[]> KEYBOARD = Map.of(
2    '2', "abc".toCharArray(),
3    '3', "def".toCharArray(),
4    '4', "ghi".toCharArray(),
5    '5', "jkl".toCharArray(),
6    '6', "mno".toCharArray(),
7    '7', "pqrs".toCharArray(),
8    '8', "tuv".toCharArray(),
9    '9', "wxyz".toCharArray()
10);
11
12public static List<String> letterCombinationsOfPhoneNumber(String digits) {
13    List<String> res = new ArrayList<>();
14    dfs(new StringBuilder(), res, digits.toCharArray());
15    return res;
16}
17
18private static void dfs(StringBuilder path, List<String> res, char[] digits) {
19    if (path.length() == digits.length) {
20        res.add(path.toString());
21        return;
22    }
23    char next_digit = digits[path.length()];
24    for (char letter : KEYBOARD.get(next_digit)) {
25        path.append(letter);
26        dfs(path, res, digits);
27        path.deleteCharAt(path.length() - 1);
28    }
29}
30
1const KEYBOARD = {
2    '2': 'abc',
3    '3': 'def',
4    '4': 'ghi',
5    '5': 'jkl',
6    '6': 'mno',
7    '7': 'pqrs',
8    '8': 'tuv',
9    '9': 'wxyz',
10}
11
12function letter_combinations_of_phone_number(digits) {
13    let res = [];
14    dfs(digits, [], res);
15    return res;
16}
17
18function dfs(digits, path, res) {
19    if (path.length === digits.length) {
20        res.push(path.join(''));
21        return;
22    }
23    let next_number = digits.charAt(path.length);
24    for (let letter of KEYBOARD[next_number]) {
25        path.push(letter);
26        dfs(digits, path, res);
27        path.pop();
28    }
29}
30

Recommended Readings

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

Load More