3142. Check if Grid Satisfies Conditions
Problem Description
You are given a 2D matrix grid
of size m x n
. Your task is to check whether the entire grid satisfies two specific conditions for each cell:
-
Vertical Condition: Each cell must be equal to the cell directly below it (if such a cell exists). In other words,
grid[i][j]
should equalgrid[i + 1][j]
. -
Horizontal Condition: Each cell must be different from the cell directly to its right (if such a cell exists). In other words,
grid[i][j]
should not equalgrid[i][j + 1]
.
The problem asks you to return true
if all cells in the grid satisfy both conditions, and false
if any cell violates either condition.
For example, consider a grid where:
- All values in the same column are identical (satisfying the vertical condition)
- Adjacent columns have different values (satisfying the horizontal condition)
Such a grid would return true
.
The solution iterates through each cell in the grid and checks:
- If there's a cell below (
i + 1 < m
), it verifies that the current cell equals the cell below - If there's a cell to the right (
j + 1 < n
), it verifies that the current cell differs from the cell to the right
If any cell fails either check, the function immediately returns false
. If all cells pass both checks, it returns true
.
Intuition
The key insight is that this is a straightforward validation problem - we need to verify that every cell in the grid follows two simple rules. There's no need for complex algorithms or data structures; we just need to check each cell systematically.
Think about what the conditions actually mean for the grid structure:
- The first condition (each cell equals the cell below it) means that all values in a column must be the same
- The second condition (each cell differs from the cell to its right) means that adjacent columns must have different values
This suggests the grid should look like vertical stripes, where each stripe (column) has a uniform value, and neighboring stripes have different values.
The most direct approach is to simply iterate through each cell and verify both conditions. We don't need to check every relationship twice - when we're at cell grid[i][j]
, we only need to:
- Check if it matches the cell below (if one exists)
- Check if it differs from the cell to the right (if one exists)
By checking "forward" relationships (down and right) rather than all four directions, we avoid redundant comparisons. Each relationship between adjacent cells is checked exactly once.
The early return strategy is efficient here - as soon as we find any cell that violates either condition, we know the entire grid fails the test, so we can immediately return false
. Only if we complete the entire traversal without finding violations can we confidently return true
.
Solution Approach
The solution uses a simple simulation approach, iterating through each cell in the grid and checking the two required conditions.
Implementation Steps:
-
Get grid dimensions: First, we extract the dimensions of the grid -
m
rows andn
columns usinglen(grid)
andlen(grid[0])
. -
Iterate through each cell: We use nested loops with
enumerate()
to traverse the grid. The outer loop iterates through rows (indexi
), and the inner loop iterates through columns (indexj
). Theenumerate()
function gives us both the index and the valuex
at each position. -
Check vertical condition: For each cell at position
(i, j)
, we check if there's a cell below it by verifyingi + 1 < m
. If such a cell exists, we compare the current cell's valuex
withgrid[i + 1][j]
. If they're not equal, we immediately returnFalse
since the condition is violated. -
Check horizontal condition: Similarly, we check if there's a cell to the right by verifying
j + 1 < n
. If such a cell exists, we compare the current cell's valuex
withgrid[i][j + 1]
. If they're equal, we returnFalse
since the condition requires them to be different. -
Return result: If we complete the entire traversal without finding any violations, all cells satisfy both conditions, so we return
True
.
Key Implementation Details:
- The boundary checks (
i + 1 < m
andj + 1 < n
) ensure we don't access indices outside the grid boundaries - The use of early return (
return False
) as soon as a violation is found makes the solution efficient - The conditions are checked in the exact form specified: equality for vertical neighbors and inequality for horizontal neighbors
Time Complexity: O(m × n)
where m
is the number of rows and n
is the number of columns, as we visit each cell exactly once.
Space Complexity: O(1)
as we only use a constant amount of extra space for variables.
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 this 3×4 grid:
grid = [[1, 2, 1, 2], [1, 2, 1, 2], [1, 2, 1, 2]]
We'll iterate through each cell and check both conditions:
Step 1: Cell (0,0) with value 1
- Check below: grid[0][0] = 1, grid[1][0] = 1 ✓ (equal)
- Check right: grid[0][0] = 1, grid[0][1] = 2 ✓ (different)
Step 2: Cell (0,1) with value 2
- Check below: grid[0][1] = 2, grid[1][1] = 2 ✓ (equal)
- Check right: grid[0][1] = 2, grid[0][2] = 1 ✓ (different)
Step 3: Cell (0,2) with value 1
- Check below: grid[0][2] = 1, grid[1][2] = 1 ✓ (equal)
- Check right: grid[0][2] = 1, grid[0][3] = 2 ✓ (different)
Step 4: Cell (0,3) with value 2
- Check below: grid[0][3] = 2, grid[1][3] = 2 ✓ (equal)
- Check right: No cell to the right (j+1 = 4 >= n) - skip this check
Step 5: Cell (1,0) with value 1
- Check below: grid[1][0] = 1, grid[2][0] = 1 ✓ (equal)
- Check right: grid[1][0] = 1, grid[1][1] = 2 ✓ (different)
We continue this process for all remaining cells. Notice that:
- Cells in the last row (row 2) don't need vertical checks since there's no row below
- Cells in the last column (column 3) don't need horizontal checks since there's no column to the right
In this example, all cells satisfy both conditions:
- Each column has the same value throughout (column 0 has all 1s, column 1 has all 2s, etc.)
- Adjacent columns have different values (1→2→1→2)
The function returns True
.
Counter-example: If we had a grid like:
grid = [[1, 1], [2, 1]]
At cell (0,0) with value 1:
- Check below: grid[0][0] = 1, grid[1][0] = 2 ✗ (not equal)
The function would immediately return False
without checking other cells.
Solution Implementation
1class Solution:
2 def satisfiesConditions(self, grid: List[List[int]]) -> bool:
3 """
4 Check if a grid satisfies the following conditions:
5 1. All cells in the same column must have the same value
6 2. Adjacent cells in the same row must have different values
7
8 Args:
9 grid: 2D list of integers representing the grid
10
11 Returns:
12 bool: True if grid satisfies both conditions, False otherwise
13 """
14 # Get grid dimensions
15 rows, cols = len(grid), len(grid[0])
16
17 # Iterate through each cell in the grid
18 for row_idx, row in enumerate(grid):
19 for col_idx, current_value in enumerate(row):
20 # Check condition 1: Cell below must have same value (if exists)
21 if row_idx + 1 < rows and current_value != grid[row_idx + 1][col_idx]:
22 return False
23
24 # Check condition 2: Cell to the right must have different value (if exists)
25 if col_idx + 1 < cols and current_value == grid[row_idx][col_idx + 1]:
26 return False
27
28 # All conditions satisfied
29 return True
30
1class Solution {
2 /**
3 * Checks if a grid satisfies the following conditions:
4 * 1. All cells below each cell must have the same value (column consistency)
5 * 2. Adjacent cells in the same row must have different values (row alternation)
6 *
7 * @param grid 2D integer array to check
8 * @return true if grid satisfies both conditions, false otherwise
9 */
10 public boolean satisfiesConditions(int[][] grid) {
11 // Get grid dimensions
12 int numRows = grid.length;
13 int numCols = grid[0].length;
14
15 // Iterate through each cell in the grid
16 for (int row = 0; row < numRows; row++) {
17 for (int col = 0; col < numCols; col++) {
18 // Check vertical condition: current cell must equal cell below (if exists)
19 if (row + 1 < numRows && grid[row][col] != grid[row + 1][col]) {
20 return false;
21 }
22
23 // Check horizontal condition: current cell must differ from right neighbor (if exists)
24 if (col + 1 < numCols && grid[row][col] == grid[row][col + 1]) {
25 return false;
26 }
27 }
28 }
29
30 // All conditions satisfied
31 return true;
32 }
33}
34
1class Solution {
2public:
3 bool satisfiesConditions(vector<vector<int>>& grid) {
4 // Get grid dimensions
5 int rows = grid.size();
6 int cols = grid[0].size();
7
8 // Iterate through each cell in the grid
9 for (int row = 0; row < rows; ++row) {
10 for (int col = 0; col < cols; ++col) {
11 // Check vertical condition: current cell must equal cell below (if exists)
12 if (row + 1 < rows && grid[row][col] != grid[row + 1][col]) {
13 return false;
14 }
15
16 // Check horizontal condition: current cell must not equal cell to the right (if exists)
17 if (col + 1 < cols && grid[row][col] == grid[row][col + 1]) {
18 return false;
19 }
20 }
21 }
22
23 // All conditions are satisfied
24 return true;
25 }
26};
27
1/**
2 * Checks if a grid satisfies specific conditions:
3 * - All cells in the same column must have the same value
4 * - All cells in the same row must have different values
5 *
6 * @param grid - 2D array of numbers to check
7 * @returns true if grid satisfies conditions, false otherwise
8 */
9function satisfiesConditions(grid: number[][]): boolean {
10 // Get grid dimensions
11 const rows: number = grid.length;
12 const cols: number = grid[0].length;
13
14 // Iterate through each cell in the grid
15 for (let row: number = 0; row < rows; row++) {
16 for (let col: number = 0; col < cols; col++) {
17 // Check if current cell value differs from the cell below (same column)
18 // All cells in a column should have the same value
19 if (row + 1 < rows && grid[row][col] !== grid[row + 1][col]) {
20 return false;
21 }
22
23 // Check if current cell value equals the cell to the right (same row)
24 // All cells in a row should have different values
25 if (col + 1 < cols && grid[row][col] === grid[row][col + 1]) {
26 return false;
27 }
28 }
29 }
30
31 // Grid satisfies all conditions
32 return true;
33}
34
Time and Space Complexity
Time Complexity: O(m × n)
The algorithm iterates through every element in the grid exactly once using nested loops. The outer loop runs m
times (number of rows), and for each row, the inner loop runs n
times (number of columns). For each element at position (i, j)
, the algorithm performs constant-time operations:
- Checking if there exists a cell below:
i + 1 < m
and comparing valuesx != grid[i + 1][j]
- Checking if there exists a cell to the right:
j + 1 < n
and comparing valuesx == grid[i][j + 1]
Since we visit each of the m × n
cells once and perform O(1)
operations per cell, the total time complexity is O(m × n)
.
Space Complexity: O(1)
The algorithm uses only a constant amount of extra space:
- Variables
m
andn
to store the dimensions of the grid - Loop variables
i
,j
, andx
from the enumerate functions - The
row
reference variable
These variables don't scale with the input size, as no additional data structures like arrays, lists, or recursive call stacks are created. The algorithm operates directly on the input grid without requiring auxiliary space proportional to the input size, resulting in O(1)
space complexity.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Incorrect Boundary Checking Order
A common mistake is checking the cell values before verifying if the neighboring cell exists within bounds. This leads to IndexError
exceptions.
Incorrect approach:
# Wrong - checking value before boundary if grid[i][j] != grid[i + 1][j] and i + 1 < rows: return False
Correct approach:
# Right - checking boundary first if i + 1 < rows and grid[i][j] != grid[i + 1][j]: return False
The short-circuit evaluation in Python ensures that if i + 1 < rows
is False
, the second condition won't be evaluated, preventing index errors.
2. Confusing the Conditions
Another frequent error is mixing up which condition applies to which direction:
- Vertical (same column): Values must be equal
- Horizontal (same row): Values must be different
Incorrect logic:
# Wrong - reversed conditions if i + 1 < rows and grid[i][j] == grid[i + 1][j]: # Should be != return False if j + 1 < cols and grid[i][j] != grid[i][j + 1]: # Should be == return False
3. Edge Case: Single Cell Grid
While the provided solution handles this correctly, it's worth noting that a grid with dimensions 1x1
should return True
since there are no neighbors to violate any conditions. The boundary checks naturally handle this case, but some might overthink and add unnecessary special case handling.
4. Using Wrong Indices After enumerate()
When using enumerate()
, confusion can arise about which variable represents what:
Incorrect usage:
for i, row in enumerate(grid):
for j, val in enumerate(row):
# Wrong - using i and j incorrectly
if j + 1 < rows and val != grid[j + 1][i]: # Mixed up i and j
return False
Solution: Use descriptive variable names like row_idx
and col_idx
to avoid confusion, and remember that the first index from enumerate is always the position, not the value.
Which data structure is used in a depth first search?
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 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
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!