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

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.
