N-Queens (Backtracking)

Strings & Backtracking
avg O(n!)

N-Queens asks a simple question: place N queens on an N x N chessboard so that no two attack each other. Queens attack along rows, columns, and diagonals, so every pair must avoid all three. The answer matters less than the method: backtracking. Try a move, check for failure as early as possible, undo, and try the next thing - the same loop that powers sudoku solvers, crossword fillers, and every constraint solver you will ever meet.

Watch it try, fail, and undo

Press play - or drag the timeline and step through it yourself.
Row 1Placements 0Backtracks 0Step 1 / 110
123456
1······
2······
3······
4······
5······
6······

Place 6 queens on a 6x6 board so that no two share a column or a diagonal. Plan: one queen per row - scan each row left to right and place a queen on the first safe square.

square being tried attacked / removed the solution

Complexity

Best
O(n!)
Input already in order
Average
O(n!)
Normal mixed input
Worst
O(n!)
Worst possible input
Space
O(n)
Extra memory used

Sudoku with a pencil and an eraser

You already backtrack every time you solve a sudoku. You pencil a number into an empty square and keep going. At some point a square has no legal number left. You do not throw the puzzle away - you erase your last guess and try the next number for that square. If that square runs out of options too, you erase the guess before it. The pencil is 'try', the rule check is 'detect failure', the eraser is 'undo'. N-Queens is this exact loop, stripped down to its purest form.

How it works, step by step

  1. Work row by row. Each row must hold exactly one queen, so a partial answer is just a list of columns - one per filled row.

  2. In the current row, scan squares left to right. For each square, check the queens above: does any share this column or a diagonal?

  3. If the square is attacked, skip it. This is pruning: fail now, before wasting any work on the rows below.

  4. If the square is safe, place a queen there and move down to the next row.

  5. If no square in a row is safe, that branch is dead. Backtrack: remove the queen in the row above and keep scanning from the square after it. This undo step is what makes it backtracking.

  6. When the last row gets a queen, you have a solution. Return it - or record it and keep searching if you want all of them.

The code, in JavaScript

The clearest version: an isSafe scan over the queens already placed, and the try / recurse / undo loop. The pop() line is the heart of backtracking.

javascript
function solveNQueens(n) {
  const queens = [];   // queens[r] = column of the queen in row r

  function isSafe(row, col) {
    for (let r = 0; r < row; r++) {
      const c = queens[r];
      // same column, or same diagonal (row gap === column gap)
      if (c === col || Math.abs(c - col) === row - r) return false;
    }
    return true;
  }

  function fillRow(row) {
    if (row === n) return true;            // every row has a queen - done
    for (let col = 0; col < n; col++) {
      if (!isSafe(row, col)) continue;     // prune: fail before recursing
      queens.push(col);                    // try this square
      if (fillRow(row + 1)) return true;   // solved below? bubble up
      queens.pop();                        // UNDO - the heart of backtracking
    }
    return false;                          // dead end: nothing in this row worked
  }

  return fillRow(0) ? queens : null;
}

solveNQueens(6);   // → [1, 3, 5, 0, 2, 4]  (row 0's queen in column 1, ...)
solveNQueens(3);   // → null - a 3x3 board has no solution

Dry run: 6 queens on a 6x6 board, first solution

The same steps the visualizer plays, written as a table. Generated by running the real algorithm - not written by hand.

StepRowWhat happened
11Row 1: square 1 is safe - place a queen, go to row 2.
22Row 2: square 3 is safe - place a queen, go to row 3.
33Row 3: square 5 is safe - place a queen, go to row 4.
44Row 4: square 2 is safe - place a queen, go to row 5.
55Row 5: square 4 is safe - place a queen, go to row 6.
65No safe square in row 6 - backtrack: remove the row-5 queen and continue from the square after it.
74No safe square in row 5 - backtrack: remove the row-4 queen and continue from the square after it.
83No safe square in row 4 - backtrack: remove the row-3 queen and continue from the square after it.
93Row 3: square 6 is safe - place a queen, go to row 4.
104Row 4: square 2 is safe - place a queen, go to row 5.
114No safe square in row 5 - backtrack: remove the row-4 queen and continue from the square after it.
123No safe square in row 4 - backtrack: remove the row-3 queen and it stood on the last square, so that row is a dead end too.
132Row 3 has no squares left - backtrack again: remove the row-2 queen and continue from the square after it.
142Row 2: square 4 is safe - place a queen, go to row 3.
153Row 3: square 2 is safe - place a queen, go to row 4.
164Row 4: square 5 is safe - place a queen, go to row 5.
175Row 5: square 3 is safe - place a queen, go to row 6.
185No safe square in row 6 - backtrack: remove the row-5 queen and continue from the square after it.
194No safe square in row 5 - backtrack: remove the row-4 queen and continue from the square after it.
203No safe square in row 4 - backtrack: remove the row-3 queen and continue from the square after it.
213Row 3: square 6 is safe - place a queen, go to row 4.
224Row 4: square 3 is safe - place a queen, go to row 5.
234No safe square in row 5 - backtrack: remove the row-4 queen and continue from the square after it.
243No safe square in row 4 - backtrack: remove the row-3 queen and it stood on the last square, so that row is a dead end too.
252Row 3 has no squares left - backtrack again: remove the row-2 queen and continue from the square after it.
262Row 2: square 5 is safe - place a queen, go to row 3.
273Row 3: square 2 is safe - place a queen, go to row 4.
284Row 4: square 6 is safe - place a queen, go to row 5.
295Row 5: square 3 is safe - place a queen, go to row 6.
305No safe square in row 6 - backtrack: remove the row-5 queen and continue from the square after it.
314No safe square in row 5 - backtrack: remove the row-4 queen and it stood on the last square, so that row is a dead end too.
323Row 4 has no squares left - backtrack again: remove the row-3 queen and continue from the square after it.
332No safe square in row 3 - backtrack: remove the row-2 queen and continue from the square after it.
342Row 2: square 6 is safe - place a queen, go to row 3.
353Row 3: square 2 is safe - place a queen, go to row 4.
364Row 4: square 5 is safe - place a queen, go to row 5.
374No safe square in row 5 - backtrack: remove the row-4 queen and continue from the square after it.
383No safe square in row 4 - backtrack: remove the row-3 queen and continue from the square after it.
393Row 3: square 4 is safe - place a queen, go to row 4.
404Row 4: square 2 is safe - place a queen, go to row 5.
414No safe square in row 5 - backtrack: remove the row-4 queen and continue from the square after it.
423No safe square in row 4 - backtrack: remove the row-3 queen and continue from the square after it.
432No safe square in row 3 - backtrack: remove the row-2 queen and it stood on the last square, so that row is a dead end too.
441Row 2 has no squares left - backtrack again: remove the row-1 queen and continue from the square after it.
451Row 1: square 2 is safe - place a queen, go to row 2.
462Row 2: square 4 is safe - place a queen, go to row 3.
473Row 3: square 1 is safe - place a queen, go to row 4.
484Row 4: square 3 is safe - place a queen, go to row 5.
495Row 5: square 5 is safe - place a queen, go to row 6.
505No safe square in row 6 - backtrack: remove the row-5 queen and continue from the square after it.
514No safe square in row 5 - backtrack: remove the row-4 queen and continue from the square after it.
523No safe square in row 4 - backtrack: remove the row-3 queen and continue from the square after it.
533Row 3: square 6 is safe - place a queen, go to row 4.
544Row 4: square 1 is safe - place a queen, go to row 5.
555Row 5: square 3 is safe - place a queen, go to row 6.
566Row 6: square 5 is safe - place the last queen. Every row is filled!

Good choice when…

  • The problem is "place things under constraints": sudoku, crosswords, map coloring, exam timetables, seating plans. N-Queens is the template for all of them.
  • You need all solutions, or need to know whether any exists - backtracking explores the whole space and never misses one.
  • Constraints fail early. The sooner a partial answer can be ruled out, the more of the tree pruning cuts away - that is where backtracking wins.
  • As the cleanest way to learn recursion with state: try, recurse, undo is the pattern behind permutations, subsets, and path finding too.

Bad choice when…

  • You only need one N-Queens solution for a big N - closed-form constructions place N queens directly in O(n), no search at all.
  • The problem asks for a best value over overlapping subproblems - that is dynamic programming's job, not exhaustive search.
  • Partial answers cannot be checked early. If you can only tell good from bad on a complete answer, backtracking degrades into brute force over n^n boards.

Common mistakes

  • Forgetting the UNDO after the recursive call is THE backtracking bug. The queen (or the Set entries) leaks into sibling branches, and the search misses valid answers in ways that are miserable to debug. Every add needs a matching delete on the same path.
  • The diagonal trick trips everyone once: row - col is constant on "\" diagonals, row + col on "/" diagonals. Mixing them up passes small tests and fails later - draw the two little grids in a comment and check one square by hand.
  • Prune before recursing, not after. Checking safety per square kills bad branches at depth 1; generating full boards and validating them at the end does n^n work. On 8x8 that is the difference between milliseconds and hours.
  • N = 2 and N = 3 have NO solutions. If your function returns undefined, an empty array, or the unchanged input there, callers will crash - decide on null (or an empty list for "all solutions") and test it.

N-Queens (Backtracking) vs. its closest relatives

AlgorithmBestAverageWorstSpaceStable
N-Queens (Backtracking)this pageO(n!)O(n!)O(n!)O(n)-
Depth-First SearchO(V + E)O(V + E)O(V + E)O(V)-
Trie (Prefix Tree)O(m)O(m)O(m)O(n·m)-
Binary SearchO(1)O(log n)O(log n)O(1)-