◀ THE GRIND — BACKTRACKING

N Queens

The drill: Place n queens on an n×n board so no two attack each other — no shared row, column, or diagonal — and return every arrangement as a board of dots and queens.

THE BRIEFING — THE FULL DRILL, IN MY OWN WORDS

A board size n arrives, and the drill is to place n queens on an n×n board so that no two ever attack each other — no shared row, no shared column, and no shared diagonal in either direction.

Every valid arrangement should be returned as a full board: one queen character marking each occupied square and a filler character everywhere else, one board string per row.

There can be many valid arrangements for a given n, or none at all for small boards — every distinct arrangement found should be included, and no partial or attacking arrangement should ever appear.

EX 01
n = 1
[["Q"]]
MINIMUM SIZE, ONE QUEEN ALONE
EX 02
n = 2
[]
NO PLACEMENT ESCAPES ATTACK ON A 2X2 BOARD
EX 03
n = 3
[]
STILL NO VALID PLACEMENT ON A 3X3 BOARD
THE HINTS — TAKE ONLY WHAT YOU NEED
HINT 1 THE NUDGE

Every row can hold exactly one queen without instantly conflicting with itself, so the placement is really a choice of one column per row. What does that turn the search into?

HINT 2 THE STRUCTURE

Track which columns and which of the two diagonal directions are already covered — one diagonal direction is constant along row−col, the other along row+col. A square is safe only when none of those three sets already contains it.

HINT 3 ONE STEP FROM THE ANSWER

Backtrack row by row: try every open column in the current row, mark its column and both diagonals used, recurse to the next row, then undo the marks before trying the next column. Reaching row n with no conflicts is a finished board.

COACH'S BOARD — THE PATTERN, STEP BY STEP
THE DIAGONAL WATCHPATTERN · BACKTRACKING — COLUMN & DIAGONAL SETSn = 4 · one queen per row
STEP 1

n = 4. Place one queen per row, testing column and both diagonal sets before ever committing a square.

STEP 1 / 11 · ← → WORK TOO
THE SPLITS — TWO PACES, TWO LANGUAGES
grind/n-queens.pyRACE PACE
LANG ▸
PACE ▸
class Solution:
    def solveNQueens(self, n: int) -> List[List[str]]:
        results = []
        cols_used = set()
        diag1_used = set()  # constant along row - col
        diag2_used = set()  # constant along row + col
        placement = [0] * n

        def backtrack(row: int) -> None:
            if row == n:
                results.append(["." * c + "Q" + "." * (n - c - 1) for c in placement])
                return
            for col in range(n):
                if col in cols_used or (row - col) in diag1_used or (row + col) in diag2_used:
                    continue
                cols_used.add(col)
                diag1_used.add(row - col)
                diag2_used.add(row + col)
                placement[row] = col
                backtrack(row + 1)
                cols_used.remove(col)
                diag1_used.remove(row - col)
                diag2_used.remove(row + col)

        backtrack(0)
        return results
TIME O(N!)SPACE O(N)PYTHON · RACE PACE · 26 LN

✓ CHIP-TIMED — ALL 4 SOLUTIONS RAN GREEN AGAINST SELF-AUTHORED CASES IN CI · JDK 21 · CPYTHON 3.12 · NOTHING PUBLISHES RED