2133. Check if Every Row and Column Contains All Numbers
Problem Description
In this problem, we are given an n x n
integer matrix and we need to determine if this matrix is "valid". A matrix is considered valid if every row and every column contains all the integers from 1
to n
(inclusive). This essentially means that, in a valid matrix, each number in the range from 1
to n
should appear exactly once in each row and exactly once in each column without any repetition or omission. The function should return true
if the matrix is valid, and false
otherwise.
Intuition
To determine if the given matrix is valid, we need to verify two conditions for each number from 1
to n
:
- It appears exactly once in each row.
- It appears exactly once in each column.
Since we need to check all numbers against both rows and columns, we can tackle each one independently. Here's the intuition behind our approach:
-
For checking rows, we iterate over each row and create an array
seen
of sizen
where each element is initially set toFalse
. As we encounter a number in a row, we calculate its index in theseen
array by subtracting1
. If the corresponding index in theseen
array is alreadyTrue
, it means we have seen this number earlier in this row, which violates our condition, so we returnFalse
. If not, we set the corresponding index toTrue
. -
For checking columns, we repeat the same process but iterate column-wise instead of row-wise, hence we'll have separate iterations for rows and columns.
-
If both row-wise and column-wise iterations do not return
False
, it means that the matrix satisfies the condition of having unique numbers from1
ton
in all rows and columns, and thus, we returnTrue
, confirming that the matrix is valid.
Solution Approach
The implementation of the solution uses a straightforward approach to verify the conditions for a valid matrix. The checkValid
function is called with the matrix as input, and it is intended to return a boolean value indicating the validity of the matrix. Here's a step-by-step explanation of the solution approach:
-
We determine the size of the matrix
n
by getting the length of the matrix, which is represented as the number of rows (or columns since it isn x n
). -
The function has two nested loops for each condition, i.e., one set for checking the rows and another for checking the columns:
- For rows:
- We iterate over each row with index
i
. - Inside this loop, we initialize an array
seen
of sizen
with all values set toFalse
. This array keeps track of the numbers we have come across in the current row. - We then iterate over each element of the row with index
j
. - We calculate the value
v
by subtracting1
from the matrix elementmatrix[i][j]
, which effectively translates the value to an index that corresponds to the range[0, n-1]
. - If
seen[v]
isTrue
, it means the numberv+1
was previously encountered in the same row, thus we should returnFalse
as the row does not contain unique numbers. - If
seen[v]
isFalse
, we mark itTrue
, indicating that we've encounteredv+1
for the first time in the current row.
- We iterate over each row with index
- For columns:
- The process is similar to rows but we iterate over each column with index
j
first. - For each column, we initialize a fresh
seen
array, and then iterate over each rowi
. - We use the same logic as we did for rows to mark off seen values for the column elements.
- The process is similar to rows but we iterate over each column with index
- For rows:
-
If we successfully exit both nested loops without returning
False
, it means the matrix has passed all validation checks and we returnTrue
.
The algorithm uses an array-based implementation and checks for the presence of numbers using a boolean array. The time complexity of this algorithm is O(n^2)
since we have to check every element of an n x n
matrix twice, once for row-wise and once for column-wise uniqueness.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through an example to understand how the solution approach works. We will use a 3 x 3
matrix for this example to illustrate the validation process.
Consider the following matrix:
[[1, 2, 3], [2, 3, 1], [3, 1, 2]]
We need to determine if this matrix is valid according to the specified conditions. The conditions are that the numbers 1
to n
should appear exactly once in each row and once in each column.
Step 1: Initialization
First, we identify n
, the size of the matrix, which is 3
.
Step 2: Check Rows for Uniqueness
We initialize a seen
array for the first row and set all its values to False
[False, False, False]
.
- We look at the first element of the first row, which is
1
. Subtract1
to get the index0
. We update theseen
array at index0
toTrue
to indicate that1
has been seen:[True, False, False]
. - Next, we see the number
2
. Subtract1
to get the index1
. Update theseen
array at index1
toTrue
to indicate that2
has been seen:[True, True, False]
. - Lastly, we look at
3
. We subtract1
to get the index2
and updateseen
at index2
toTrue
, indicating that3
has been seen:[True, True, True]
.
Since we do not encounter any True
value during this process, this row passes the uniqueness check.
We repeat this process for the second and third rows and in both cases, we don’t find any duplicates.
Step 3: Check Columns for Uniqueness
We would then perform a similar check column-wise.
- For the first column with values
[1, 2, 3]
, we set aseen
array as[False, False, False]
. As we iterate through the column and mark each number as seen, ourseen
array becomes[True, True, True]
. - We do the same for the second and third columns, and in both cases, we find that each number from
1
to3
appears only once.
Once both row-wise and column-wise checks are complete without encountering any True
value in seen
for already encountered elements, we can conclude that this matrix is indeed valid, and the function would return True
.
Following the solution approach, our final output for the provided matrix [1, 2, 3], [2, 3, 1], [3, 1, 2]
would be True
, signaling that the matrix satisfies the required conditions of validity.
Solution Implementation
1class Solution:
2 def checkValid(self, matrix: List[List[int]]) -> bool:
3 # Find the size of the matrix
4 size = len(matrix)
5
6 # Check every row in the matrix
7 for row in range(size):
8 # Initialize a list to keep track of seen numbers in the current row
9 seen_row = [False] * size
10 for col in range(size):
11 # Calculate the correct index for the value considering 1-based to 0-based indexing
12 value_index = matrix[row][col] - 1
13
14 # If we have already seen this number in the current row, the matrix is not valid
15 if seen_row[value_index]:
16 return False
17
18 # Mark the number as seen in the current row
19 seen_row[value_index] = True
20
21 # Check every column in the matrix
22 for col in range(size):
23 # Initialize a list to keep track of seen numbers in the current column
24 seen_col = [False] * size
25 for row in range(size):
26 # Calculate the correct index for the value considering 1-based to 0-based indexing
27 value_index = matrix[row][col] - 1
28
29 # If we have already seen this number in the current column, the matrix is not valid
30 if seen_col[value_index]:
31 return False
32
33 # Mark the number as seen in the current column
34 seen_col[value_index] = True
35
36 # If we reach this point, the matrix has unique numbers in all rows and all columns
37 return True
38
1class Solution {
2 public boolean checkValid(int[][] matrix) {
3 // Retrieve the size of the matrix, which is a square matrix (n x n)
4 int size = matrix.length;
5
6 // Check each row in the matrix
7 for (int row = 0; row < size; ++row) {
8 // Create a tracker for seen numbers in the current row
9 boolean[] seenRow = new boolean[size];
10 for (int col = 0; col < size; ++col) {
11 // Retrieve the number and convert it to an index (0 to n-1)
12 int numberIndex = matrix[row][col] - 1;
13 // Check if the number has already been seen in the current row
14 if (seenRow[numberIndex]) {
15 // If the number is seen before, the matrix is not valid
16 return false;
17 }
18 // Mark the number as seen
19 seenRow[numberIndex] = true;
20 }
21 }
22
23 // Check each column in the matrix
24 for (int col = 0; col < size; ++col) {
25 // Create a tracker for seen numbers in the current column
26 boolean[] seenColumn = new boolean[size];
27 for (int row = 0; row < size; ++row) {
28 // Retrieve the number and convert it to an index (0 to n-1)
29 int numberIndex = matrix[row][col] - 1;
30 // Check if the number has already been seen in the current column
31 if (seenColumn[numberIndex]) {
32 // If the number is seen before, the matrix is not valid
33 return false;
34 }
35 // Mark the number as seen
36 seenColumn[numberIndex] = true;
37 }
38 }
39 // If all rows and columns contain all numbers exactly once, matrix is valid
40 return true;
41 }
42}
43
1class Solution {
2public:
3 // Function to check if the given matrix is valid
4 bool checkValid(vector<vector<int>>& matrix) {
5 int size = matrix.size(); // Get the size of the matrix
6
7 // Check each row for validity
8 for (int rowIndex = 0; rowIndex < size; ++rowIndex) {
9 vector<bool> seenInRow(size, false); // Initialize seenInRow to keep track of numbers in row
10 for (int columnIndex = 0; columnIndex < size; ++columnIndex) {
11 int value = matrix[rowIndex][columnIndex] - 1; // Zero-based index for checking
12 if (seenInRow[value]) return false; // If the number is already seen, matrix is invalid
13 seenInRow[value] = true; // Mark the number as seen for current row
14 }
15 }
16
17 // Check each column for validity
18 for (int columnIndex = 0; columnIndex < size; ++columnIndex) {
19 vector<bool> seenInColumn(size, false); // Initialize seenInColumn to keep track of numbers in column
20 for (int rowIndex = 0; rowIndex < size; ++rowIndex) {
21 int value = matrix[rowIndex][columnIndex] - 1; // Zero-based index for checking
22 if (seenInColumn[value]) return false; // If the number is already seen, matrix is invalid
23 seenInColumn[value] = true; // Mark the number as seen for current column
24 }
25 }
26
27 // If all rows and columns pass the checks, return true indicating the matrix is valid
28 return true;
29 }
30};
31
1/**
2 * Checks if a given square matrix is valid. A matrix is valid if every row and every column
3 * contains all numbers from 1 to n (where n is the number of rows/columns in the matrix) exactly once.
4 *
5 * @param {number[][]} matrix - The square matrix to check for validity.
6 * @returns {boolean} - Returns true if the matrix is valid, false otherwise.
7 */
8function checkValid(matrix: number[][]): boolean {
9 const size = matrix.length;
10
11 // Create arrays to track the presence of numbers in each row and column.
12 let rows = Array.from({ length: size }, () => new Array(size).fill(false));
13 let columns = Array.from({ length: size }, () => new Array(size).fill(false));
14
15 // Iterate over each cell in the matrix.
16 for (let i = 0; i < size; i++) {
17 for (let j = 0; j < size; j++) {
18 // Get the current value, subtracting 1 to convert it to a 0-based index.
19 let currentValue = matrix[i][j] - 1;
20
21 // Check if the current value has already been seen in the current row or column.
22 if (rows[i][currentValue] || columns[j][currentValue]) {
23 return false; // If the value has been seen, return false as the matrix is invalid.
24 }
25
26 // Mark the value as seen for the current row and column.
27 rows[i][currentValue] = true;
28 columns[j][currentValue] = true;
29 }
30 }
31
32 // If we've checked all cells and have not returned false, the matrix is valid.
33 return true;
34}
35
Time and Space Complexity
The time complexity of the code is O(n^2)
. This is because there are two nested loops, each iterating n
times, where n
is the size of the matrix's dimension (both width and height). The first loop iterates through each row while the second inner loop checks each column for validating the matrix, ensuring all numbers from 1 to n
appear exactly once in each row and column.
The space complexity of the code is O(n)
. This is because additional space is used to create the seen
array which has a size of n
. This array is used to track whether a number has been seen before in the current row or column. The seen
array is reset to False
for each row and column, but since it is reused, the space complexity does not exceed O(n)
.
Learn more about how to find time and space complexity quickly using problem constraints.
Which of these pictures shows the visit order of a depth-first search?
Recommended Readings
LeetCode 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 we
Recursion 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 algomonster s3 us east 2 amazonaws com recursion jpg You first
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!