LeetCode 3033 - Modify the Matrix
The problem is asking us to take a given m x n matrix, potentially containing -1 values, and produce a modified matrix in which each -1 is replaced by the maximum value in its respective column.
Difficulty: 🟢 Easy
Topics: Array, Matrix
Solution
Problem Understanding
The problem is asking us to take a given m x n matrix, potentially containing -1 values, and produce a modified matrix in which each -1 is replaced by the maximum value in its respective column. The input matrix is guaranteed to have at least one non-negative integer in each column, which ensures that a maximum value can always be determined. The expected output is a new matrix (or an updated copy of the original) where only -1 values are replaced, and all other values remain unchanged.
The constraints indicate the matrix is small to medium-sized, with m and n up to 50, so a simple nested iteration over columns and rows will be efficient enough. Important edge cases include columns where the -1 is at the top, bottom, or multiple -1s in a single column.
Approaches
The brute-force approach involves iterating over each cell in the matrix. For every cell with -1, we would scan its entire column to find the maximum value and replace the -1 accordingly. This method is correct, as it directly follows the problem statement, but it repeats work for columns with multiple -1s.
The optimal approach involves precomputing the maximum value for each column before modifying the matrix. Once all column maxima are known, we can iterate over the matrix again, replacing -1s with the precomputed maxima. This avoids repeated scanning and makes the solution straightforward and efficient.
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(m * n * m) | O(1) | For each -1, scans the entire column to find the maximum. Repeats work if multiple -1s exist in the same column. |
| Optimal | O(m * n) | O(n) | Precompute column maxima in one pass, then modify the matrix in a second pass. Efficient for the given constraints. |
Algorithm Walkthrough
- Initialize a list
col_maxof sizento store the maximum value for each column. Start with a very low initial value (e.g.,-inf) to ensure any valid matrix value will replace it. - Iterate over each column index
jfrom0ton-1. For each column, iterate over all rowsiand updatecol_max[j]with the maximum value found in that column, ignoring-1values. - Iterate over the matrix again. For each cell
matrix[i][j], check if the value is-1. If it is, replace it withcol_max[j]. - Return the modified matrix.
Why it works: By precomputing the maximum value for each column, we ensure that each -1 is replaced with the correct maximum without repeatedly scanning the column. Since the constraints guarantee at least one non-negative integer per column, the col_max list will always contain a valid replacement.
Python Solution
from typing import List
class Solution:
def modifiedMatrix(self, matrix: List[List[int]]) -> List[List[int]]:
m, n = len(matrix), len(matrix[0])
col_max = [-1] * n
# Step 1: compute maximum for each column
for j in range(n):
for i in range(m):
if matrix[i][j] != -1:
col_max[j] = max(col_max[j], matrix[i][j])
# Step 2: replace -1 with column maximum
for i in range(m):
for j in range(n):
if matrix[i][j] == -1:
matrix[i][j] = col_max[j]
return matrix
The first nested loop computes the column maxima efficiently in O(m * n). The second loop iterates over the matrix again to replace all -1s using the precomputed maxima. This separation of concerns ensures clarity and avoids redundant computations.
Go Solution
func modifiedMatrix(matrix [][]int) [][]int {
m, n := len(matrix), len(matrix[0])
colMax := make([]int, n)
// Initialize colMax with -1
for j := 0; j < n; j++ {
colMax[j] = -1
}
// Step 1: compute maximum for each column
for j := 0; j < n; j++ {
for i := 0; i < m; i++ {
if matrix[i][j] != -1 && matrix[i][j] > colMax[j] {
colMax[j] = matrix[i][j]
}
}
}
// Step 2: replace -1 with column maximum
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if matrix[i][j] == -1 {
matrix[i][j] = colMax[j]
}
}
}
return matrix
}
Go implementation mirrors the Python logic closely, using slices for column maxima and standard for loops. We avoid nil slices, and integer comparisons are safe because all input values are within the -1 to 100 range.
Worked Examples
Example 1
Input: [[1,2,-1],[4,-1,6],[7,8,9]]
Step 1: Compute column maxima:
- Column 0: max(1,4,7) = 7
- Column 1: max(2, - , 8) = 8
- Column 2: max(- , 6, 9) = 9
Step 2: Replace -1 with column maxima:
- matrix[0][2] = 9
- matrix[1][1] = 8
Output: [[1,2,9],[4,8,6],[7,8,9]]
Example 2
Input: [[3,-1],[5,2]]
Column maxima:
- Column 0: max(3,5) = 5
- Column 1: max(- ,2) = 2
Replace -1:
- matrix[0][1] = 2
Output: [[3,2],[5,2]]
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(m * n) | Two passes over the matrix, each visiting all elements. |
| Space | O(n) | Extra space for storing column maxima. |
The algorithm is efficient and well within the problem constraints, as m and n are at most 50.
Test Cases
# Provided examples
assert Solution().modifiedMatrix([[1,2,-1],[4,-1,6],[7,8,9]]) == [[1,2,9],[4,8,6],[7,8,9]] # replaces -1 correctly
assert Solution().modifiedMatrix([[3,-1],[5,2]]) == [[3,2],[5,2]] # handles small matrix
# Edge cases
assert Solution().modifiedMatrix([[-1,-1],[-1,-1]]) == [[-1,-1],[-1,-1]] # all -1, no valid max to replace
assert Solution().modifiedMatrix([[0,-1],[-1,1]]) == [[0,1],[0,1]] # zeros and ones
assert Solution().modifiedMatrix([[10]]) == [[10]] # 1x1 matrix, no -1
# Larger matrix
matrix = [[i if (i+j)%3 != 0 else -1 for j in range(5)] for i in range(5)]
expected = [row[:] for row in matrix]
for j in range(5):
col_max = max(matrix[i][j] for i in range(5) if matrix[i][j] != -1)
for i in range(5):
if expected[i][j] == -1:
expected[i][j] = col_max
assert Solution().modifiedMatrix(matrix) == expected
| Test | Why |
|---|---|
| Provided examples | Validates basic functionality and correctness |
| All -1 | Checks handling when no replacement is possible |
| Zeros and ones | Confirms correct handling of boundary values |
| 1x1 matrix | Minimal input validation |
| Larger matrix | Tests algorithm on moderately sized input and multiple -1s per column |
Edge Cases
One edge case is when a column contains multiple -1s. A naive approach that recomputes the maximum for each -1 would be inefficient, but the precomputation handles it seamlessly.
Another edge case is when the -1 is the only negative value in a column, while all other values are zero or positive. The algorithm correctly finds the maximum among valid values, avoiding replacing -1 with another -1.
A final edge case is a minimal matrix, such as 1x1 or 2x2, which could break indexing logic. The implementation handles these naturally by iterating over the matrix size and using precomputed column maxima.