Files
codetutor/backend/data/questions/check-if-matrix-is-x-matrix.yaml

186 lines
8.1 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
title: Check if Matrix Is X-Matrix
slug: check-if-matrix-is-x-matrix
difficulty: easy
leetcode_id: 2319
leetcode_url: https://leetcode.com/problems/check-if-matrix-is-x-matrix/
categories:
- arrays
- math
patterns:
- matrix-traversal
function_signature: "def check_x_matrix(grid: list[list[int]]) -> bool:"
test_cases:
visible:
- input: { grid: [[2, 0, 0, 1], [0, 3, 1, 0], [0, 5, 2, 0], [4, 0, 0, 2]] }
expected: true
- input: { grid: [[5, 7, 0], [0, 3, 1], [0, 5, 0]] }
expected: false
hidden:
- input: { grid: [[1, 0, 1], [0, 1, 0], [1, 0, 1]] }
expected: true
- input: { grid: [[1, 0, 0], [0, 1, 0], [0, 0, 1]] }
expected: false
- input: { grid: [[0, 0, 1], [0, 1, 0], [1, 0, 0]] }
expected: false
- input: { grid: [[5, 0, 5], [0, 5, 0], [5, 0, 5]] }
expected: true
description: |
A square matrix is said to be an **X-Matrix** if **both** of the following conditions hold:
1. All the elements in the diagonals of the matrix are **non-zero**.
2. All other elements are `0`.
Given a 2D integer array `grid` of size `n x n` representing a square matrix, return `true` *if* `grid` *is an X-Matrix*. Otherwise, return `false`.
constraints: |
- `n == grid.length == grid[i].length`
- `3 <= n <= 100`
- `0 <= grid[i][j] <= 10^5`
examples:
- input: "grid = [[2,0,0,1],[0,3,1,0],[0,5,2,0],[4,0,0,2]]"
output: "true"
explanation: "The diagonal elements (positions where i == j or i + j == n - 1) are all non-zero: 2, 1, 3, 1, 5, 2, 4, 2. All other elements are 0. Thus, grid is an X-Matrix."
- input: "grid = [[5,7,0],[0,3,1],[0,5,0]]"
output: "false"
explanation: "The element at position (0,1) is 7, which should be 0 since it's not on a diagonal. Also, position (1,2) is 1 instead of 0. Thus, grid is not an X-Matrix."
explanation:
intuition: |
Imagine drawing a large "X" across a square grid. The "X" touches the four corners and crosses in the center. These positions form the **two diagonals** of the matrix:
- **Primary diagonal**: runs from top-left to bottom-right (where row index equals column index: `i == j`)
- **Anti-diagonal**: runs from top-right to bottom-left (where row plus column equals `n - 1`: `i + j == n - 1`)
Think of it like this: you're a quality inspector checking each cell of the grid. At every position, you need to answer one question: "Am I on a diagonal?" If yes, the value must be non-zero. If no, the value must be zero.
The key insight is that determining whether a position `(i, j)` lies on a diagonal is a simple mathematical check — no need to pre-compute or store the diagonal positions. This allows us to verify the X-Matrix property in a single pass through the grid.
approach: |
We solve this using a **Single Pass Matrix Traversal**:
**Step 1: Iterate through every cell**
- Use nested loops to visit each position `(i, j)` in the grid
- For each cell, determine if it lies on a diagonal
&nbsp;
**Step 2: Check diagonal membership**
- A cell `(i, j)` is on the primary diagonal if `i == j`
- A cell `(i, j)` is on the anti-diagonal if `i + j == n - 1`
- Combined: a cell is on *some* diagonal if `i == j` or `i + j == n - 1`
&nbsp;
**Step 3: Validate the cell value**
- If the cell is on a diagonal: check that `grid[i][j] != 0`
- If the cell is NOT on a diagonal: check that `grid[i][j] == 0`
- If any check fails, immediately return `false`
&nbsp;
**Step 4: Return the result**
- If we complete the traversal without finding any violations, return `true`
&nbsp;
This approach works because we exhaustively check every cell exactly once, ensuring both conditions of the X-Matrix definition are satisfied.
common_pitfalls:
- title: Forgetting the Anti-Diagonal
description: |
A common mistake is only checking the primary diagonal (`i == j`) and forgetting that the anti-diagonal (`i + j == n - 1`) is also part of the "X" shape.
For example, in a 3x3 grid, position `(0, 2)` and `(2, 0)` are on the anti-diagonal but not the primary diagonal. Missing this check would incorrectly require these cells to be zero.
wrong_approach: "Only checking i == j for diagonals"
correct_approach: "Check both i == j and i + j == n - 1"
- title: Off-By-One in Anti-Diagonal Check
description: |
The anti-diagonal condition is `i + j == n - 1`, not `i + j == n`. Remember that indices are 0-based, so for an `n x n` matrix, the anti-diagonal connects positions like `(0, n-1)`, `(1, n-2)`, ..., `(n-1, 0)`.
If you use `i + j == n`, you'll be checking positions that don't exist or missing the actual anti-diagonal.
wrong_approach: "Using i + j == n for anti-diagonal"
correct_approach: "Use i + j == n - 1 for anti-diagonal"
- title: Checking Only One Condition
description: |
Both conditions must be checked for every cell:
- Diagonal cells must be **non-zero**
- Non-diagonal cells must be **zero**
Some solutions only verify that diagonals are non-zero, forgetting to check that everything else is zero, or vice versa.
wrong_approach: "Only checking diagonals are non-zero, ignoring other cells"
correct_approach: "Verify both conditions: diagonals non-zero AND others zero"
key_takeaways:
- "**Diagonal identification**: In an `n x n` matrix, primary diagonal positions satisfy `i == j`, anti-diagonal positions satisfy `i + j == n - 1`"
- "**Early exit optimisation**: Return `false` immediately upon finding any violation rather than checking all cells first"
- "**Matrix traversal pattern**: Nested loops with `O(n^2)` complexity are acceptable when you must inspect every cell"
- "**Simple validation problems**: When verifying properties, translate the definition directly into conditional checks"
time_complexity: "O(n^2). We visit each of the n × n cells exactly once to verify its value."
space_complexity: "O(1). We only use a constant amount of extra space for loop variables and comparisons."
solutions:
- approach_name: Single Pass Validation
is_optimal: true
code: |
def check_x_matrix(grid: list[list[int]]) -> bool:
n = len(grid)
for i in range(n):
for j in range(n):
# Check if this position is on either diagonal
on_diagonal = (i == j) or (i + j == n - 1)
if on_diagonal:
# Diagonal elements must be non-zero
if grid[i][j] == 0:
return False
else:
# Non-diagonal elements must be zero
if grid[i][j] != 0:
return False
# All checks passed
return True
explanation: |
**Time Complexity:** O(n^2) — We iterate through all n × n cells once.
**Space Complexity:** O(1) — Only a few variables used regardless of input size.
We check each cell exactly once. For diagonal positions (where `i == j` or `i + j == n - 1`), we verify the value is non-zero. For all other positions, we verify the value is zero. Any violation causes an immediate return of `false`.
- approach_name: Condensed Boolean Check
is_optimal: true
code: |
def check_x_matrix(grid: list[list[int]]) -> bool:
n = len(grid)
for i in range(n):
for j in range(n):
on_diagonal = (i == j) or (i + j == n - 1)
# XOR-like logic: diagonal and non-zero, or not diagonal and zero
if on_diagonal != (grid[i][j] != 0):
return False
return True
explanation: |
**Time Complexity:** O(n^2) — Same traversal as the first approach.
**Space Complexity:** O(1) — Constant extra space.
This condensed version uses a clever boolean comparison. The condition `on_diagonal != (grid[i][j] != 0)` returns `True` (invalid) when:
- The cell is on a diagonal but has value 0, OR
- The cell is not on a diagonal but has a non-zero value
Both cases represent violations of the X-Matrix property.