Facebook Pixel

3033. Modify the Matrix

Problem Description

You are given a 2D integer matrix (0-indexed) with m rows and n columns. Your task is to create a new matrix called answer that starts as a copy of the original matrix, but with a modification: every element that has value -1 should be replaced with the maximum value found in that element's column.

For example, if a column contains values [3, -1, 5, 2], the maximum value in that column is 5, so any -1 in that column would be replaced with 5.

The solution works by:

  1. First iterating through each column j from 0 to n-1
  2. For each column, finding the maximum value by checking all rows in that column using max(matrix[i][j] for i in range(m))
  3. Then going through that same column again and replacing any -1 values with the maximum value found
  4. Finally returning the modified matrix

The time complexity is O(m × n) since we visit each element twice (once to find the maximum, once to potentially replace), and the space complexity is O(1) as we modify the matrix in-place.

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 process the matrix column by column rather than row by row, since the replacement value for each -1 depends on the maximum value in its column.

When we see a -1 in the matrix, we can't immediately know what to replace it with - we need to examine all values in that column first to find the maximum. This suggests a two-pass approach for each column:

  1. First pass: Scan the entire column to find the maximum value
  2. Second pass: Replace any -1 values with that maximum

Why can't we do this in a single pass? If we tried to replace -1 values as we encounter them, we might miss a larger value that appears later in the column. For instance, if a column has values [-1, 3, 5, 2], we can't replace the -1 until we've seen all values and discovered that 5 is the maximum.

The solution naturally follows this observation: iterate through each column, find its maximum value (which automatically ignores -1 values since they're negative and we're looking for the maximum), then make another pass through the same column to perform the replacements. Since each column's replacements are independent of other columns, we can process them one at a time in any order.

This approach modifies the matrix in-place, which is efficient since we don't need extra space for a new matrix - we can directly update the -1 values where they appear.

Solution Approach

Following the simulation approach, we implement the solution by processing each column independently:

Step 1: Get matrix dimensions

m, n = len(matrix), len(matrix[0])

We store the number of rows m and columns n for easy reference.

Step 2: Process each column

for j in range(n):

We iterate through each column index from 0 to n-1.

Step 3: Find the maximum value in the current column

mx = max(matrix[i][j] for i in range(m))

For column j, we use a generator expression with Python's max() function to find the maximum value across all rows. This examines matrix[0][j], matrix[1][j], ..., matrix[m-1][j] and returns the largest value. Since -1 is negative and we're looking for the maximum, any positive values in the column will naturally be selected over -1.

Step 4: Replace -1 values with the maximum

for i in range(m):
    if matrix[i][j] == -1:
        matrix[i][j] = mx

We iterate through the same column again, checking each element. If an element equals -1, we replace it with the maximum value mx we found in Step 3.

Step 5: Return the modified matrix

return matrix

After processing all columns, we return the modified matrix. Note that we modified the original matrix in-place rather than creating a new one.

The algorithm processes each element exactly twice - once during the maximum-finding pass and once during the replacement pass - giving us O(m × n) time complexity with O(1) extra space.

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 to illustrate the solution approach.

Given matrix:

[[ 1, -1,  3],
 [-1,  5, -1],
 [ 2, -1,  4]]

Step 1: Get dimensions

  • m = 3 (rows), n = 3 (columns)

Step 2: Process Column 0 (j = 0)

  • Find maximum: Check matrix[0][0]=1, matrix[1][0]=-1, matrix[2][0]=2
  • Maximum value: mx = 2
  • Replace -1s: matrix[1][0] is -1, so replace with 2
  • Matrix after column 0:
[[ 1, -1,  3],
 [ 2,  5, -1],
 [ 2, -1,  4]]

Step 3: Process Column 1 (j = 1)

  • Find maximum: Check matrix[0][1]=-1, matrix[1][1]=5, matrix[2][1]=-1
  • Maximum value: mx = 5
  • Replace -1s: matrix[0][1] and matrix[2][1] are both -1, replace with 5
  • Matrix after column 1:
[[ 1,  5,  3],
 [ 2,  5, -1],
 [ 2,  5,  4]]

Step 4: Process Column 2 (j = 2)

  • Find maximum: Check matrix[0][2]=3, matrix[1][2]=-1, matrix[2][2]=4
  • Maximum value: mx = 4
  • Replace -1s: matrix[1][2] is -1, so replace with 4
  • Final matrix:
[[ 1,  5,  3],
 [ 2,  5,  4],
 [ 2,  5,  4]]

Each -1 has been replaced with the maximum value from its respective column: column 0's max was 2, column 1's max was 5, and column 2's max was 4.

Solution Implementation

1class Solution:
2    def modifiedMatrix(self, matrix: List[List[int]]) -> List[List[int]]:
3        # Get dimensions of the matrix
4        num_rows, num_cols = len(matrix), len(matrix[0])
5      
6        # Process each column
7        for col in range(num_cols):
8            # Find the maximum value in the current column
9            max_value = max(matrix[row][col] for row in range(num_rows))
10          
11            # Replace all -1 values in the current column with the maximum value
12            for row in range(num_rows):
13                if matrix[row][col] == -1:
14                    matrix[row][col] = max_value
15      
16        # Return the modified matrix
17        return matrix
18
1class Solution {
2    /**
3     * Modifies a matrix by replacing all -1 values with the maximum value in their respective column.
4     * 
5     * @param matrix The input matrix to be modified
6     * @return The modified matrix with -1 values replaced
7     */
8    public int[][] modifiedMatrix(int[][] matrix) {
9        // Get matrix dimensions
10        int numRows = matrix.length;
11        int numCols = matrix[0].length;
12      
13        // Process each column
14        for (int col = 0; col < numCols; col++) {
15            // Find the maximum value in the current column
16            int maxValueInColumn = -1;
17            for (int row = 0; row < numRows; row++) {
18                maxValueInColumn = Math.max(maxValueInColumn, matrix[row][col]);
19            }
20          
21            // Replace all -1 values in the current column with the maximum value
22            for (int row = 0; row < numRows; row++) {
23                if (matrix[row][col] == -1) {
24                    matrix[row][col] = maxValueInColumn;
25                }
26            }
27        }
28      
29        return matrix;
30    }
31}
32
1class Solution {
2public:
3    vector<vector<int>> modifiedMatrix(vector<vector<int>>& matrix) {
4        // Get matrix dimensions
5        int rows = matrix.size();
6        int cols = matrix[0].size();
7      
8        // Process each column independently
9        for (int col = 0; col < cols; ++col) {
10            // Find the maximum value in the current column
11            int maxValue = -1;
12            for (int row = 0; row < rows; ++row) {
13                maxValue = max(maxValue, matrix[row][col]);
14            }
15          
16            // Replace all -1 values in the current column with the maximum value
17            for (int row = 0; row < rows; ++row) {
18                if (matrix[row][col] == -1) {
19                    matrix[row][col] = maxValue;
20                }
21            }
22        }
23      
24        // Return the modified matrix
25        return matrix;
26    }
27};
28
1/**
2 * Modifies a matrix by replacing all -1 values in each column with the maximum value in that column
3 * @param matrix - The input matrix to be modified
4 * @returns The modified matrix with -1 values replaced
5 */
6function modifiedMatrix(matrix: number[][]): number[][] {
7    // Get matrix dimensions
8    const rowCount: number = matrix.length;
9    const columnCount: number = matrix[0].length;
10  
11    // Process each column
12    for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {
13        // Find the maximum value in the current column
14        let maxValueInColumn: number = -1;
15        for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
16            maxValueInColumn = Math.max(maxValueInColumn, matrix[rowIndex][columnIndex]);
17        }
18      
19        // Replace all -1 values in the current column with the maximum value
20        for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
21            if (matrix[rowIndex][columnIndex] === -1) {
22                matrix[rowIndex][columnIndex] = maxValueInColumn;
23            }
24        }
25    }
26  
27    return matrix;
28}
29

Time and Space Complexity

The time complexity is O(m × n), where m and n are the number of rows and columns of the matrix, respectively. This is because:

  • The outer loop iterates through all n columns
  • For each column, we find the maximum value by iterating through all m rows, which takes O(m) time
  • Then we iterate through all m rows again to replace -1 values, which also takes O(m) time
  • Total: n × (m + m) = n × 2m = O(m × n)

The space complexity is O(1) as the algorithm modifies the matrix in-place and only uses a constant amount of extra space for variables like m, n, mx, i, and j, regardless of the input size.

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

Common Pitfalls

Pitfall 1: Assuming the Maximum Value Exists When All Elements are -1

Issue: If a column contains only -1 values, the maximum value in that column would be -1 itself. This means all -1 values in that column would be replaced with -1, leaving them unchanged. While this is technically correct behavior, it might not be the intended result in some problem variations.

Example:

matrix = [[1, -1, 3],
          [2, -1, 4],
          [5, -1, 6]]
# Column 1 has all -1s, so max is -1
# Result: no change in column 1

Solution: If the problem requires handling all-negative columns differently, you could add a check:

for col in range(num_cols):
    # Find the maximum value in the current column
    max_value = max(matrix[row][col] for row in range(num_rows))
  
    # Only replace if we found a non-negative maximum
    if max_value != -1:
        for row in range(num_rows):
            if matrix[row][col] == -1:
                matrix[row][col] = max_value

Pitfall 2: Modifying the Original Matrix When a Copy is Expected

Issue: The current solution modifies the input matrix in-place. If the caller expects the original matrix to remain unchanged (as suggested by the problem statement mentioning "create a new matrix called answer"), this could cause unexpected side effects.

Example:

original = [[1, -1], [3, 4]]
result = solution.modifiedMatrix(original)
# Now original is also [[1, 4], [3, 4]] - original data is lost!

Solution: Create a deep copy of the matrix first:

import copy

class Solution:
    def modifiedMatrix(self, matrix: List[List[int]]) -> List[List[int]]:
        # Create a deep copy to avoid modifying the original
        answer = copy.deepcopy(matrix)
        num_rows, num_cols = len(answer), len(answer[0])
      
        for col in range(num_cols):
            max_value = max(matrix[row][col] for row in range(num_rows))
            for row in range(num_rows):
                if answer[row][col] == -1:
                    answer[row][col] = max_value
      
        return answer

Pitfall 3: Empty Matrix or Single Element Edge Cases

Issue: The code assumes the matrix has at least one row and one column. An empty matrix or edge cases might cause errors.

Example:

matrix = []  # This would cause an IndexError when accessing matrix[0]
matrix = [[]]  # This would work but might not be intended behavior

Solution: Add validation at the beginning:

def modifiedMatrix(self, matrix: List[List[int]]) -> List[List[int]]:
    # Handle edge cases
    if not matrix or not matrix[0]:
        return matrix
  
    num_rows, num_cols = len(matrix), len(matrix[0])
    # ... rest of the code
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

A heap is a ...?


Recommended Readings

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

Load More