N-Queens (Backtracking)
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.| 1 | 2 | 3 | 4 | 5 | 6 | |
|---|---|---|---|---|---|---|
| 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.
Complexity
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
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.
In the current row, scan squares left to right. For each square, check the queens above: does any share this column or a diagonal?
If the square is attacked, skip it. This is pruning: fail now, before wasting any work on the rows below.
If the square is safe, place a queen there and move down to the next row.
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.
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.
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 solutionDry 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.
| Step | Row | What happened |
|---|---|---|
| 1 | 1 | Row 1: square 1 is safe - place a queen, go to row 2. |
| 2 | 2 | Row 2: square 3 is safe - place a queen, go to row 3. |
| 3 | 3 | Row 3: square 5 is safe - place a queen, go to row 4. |
| 4 | 4 | Row 4: square 2 is safe - place a queen, go to row 5. |
| 5 | 5 | Row 5: square 4 is safe - place a queen, go to row 6. |
| 6 | 5 | No safe square in row 6 - backtrack: remove the row-5 queen and continue from the square after it. |
| 7 | 4 | No safe square in row 5 - backtrack: remove the row-4 queen and continue from the square after it. |
| 8 | 3 | No safe square in row 4 - backtrack: remove the row-3 queen and continue from the square after it. |
| 9 | 3 | Row 3: square 6 is safe - place a queen, go to row 4. |
| 10 | 4 | Row 4: square 2 is safe - place a queen, go to row 5. |
| 11 | 4 | No safe square in row 5 - backtrack: remove the row-4 queen and continue from the square after it. |
| 12 | 3 | No 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. |
| 13 | 2 | Row 3 has no squares left - backtrack again: remove the row-2 queen and continue from the square after it. |
| 14 | 2 | Row 2: square 4 is safe - place a queen, go to row 3. |
| 15 | 3 | Row 3: square 2 is safe - place a queen, go to row 4. |
| 16 | 4 | Row 4: square 5 is safe - place a queen, go to row 5. |
| 17 | 5 | Row 5: square 3 is safe - place a queen, go to row 6. |
| 18 | 5 | No safe square in row 6 - backtrack: remove the row-5 queen and continue from the square after it. |
| 19 | 4 | No safe square in row 5 - backtrack: remove the row-4 queen and continue from the square after it. |
| 20 | 3 | No safe square in row 4 - backtrack: remove the row-3 queen and continue from the square after it. |
| 21 | 3 | Row 3: square 6 is safe - place a queen, go to row 4. |
| 22 | 4 | Row 4: square 3 is safe - place a queen, go to row 5. |
| 23 | 4 | No safe square in row 5 - backtrack: remove the row-4 queen and continue from the square after it. |
| 24 | 3 | No 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. |
| 25 | 2 | Row 3 has no squares left - backtrack again: remove the row-2 queen and continue from the square after it. |
| 26 | 2 | Row 2: square 5 is safe - place a queen, go to row 3. |
| 27 | 3 | Row 3: square 2 is safe - place a queen, go to row 4. |
| 28 | 4 | Row 4: square 6 is safe - place a queen, go to row 5. |
| 29 | 5 | Row 5: square 3 is safe - place a queen, go to row 6. |
| 30 | 5 | No safe square in row 6 - backtrack: remove the row-5 queen and continue from the square after it. |
| 31 | 4 | No 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. |
| 32 | 3 | Row 4 has no squares left - backtrack again: remove the row-3 queen and continue from the square after it. |
| 33 | 2 | No safe square in row 3 - backtrack: remove the row-2 queen and continue from the square after it. |
| 34 | 2 | Row 2: square 6 is safe - place a queen, go to row 3. |
| 35 | 3 | Row 3: square 2 is safe - place a queen, go to row 4. |
| 36 | 4 | Row 4: square 5 is safe - place a queen, go to row 5. |
| 37 | 4 | No safe square in row 5 - backtrack: remove the row-4 queen and continue from the square after it. |
| 38 | 3 | No safe square in row 4 - backtrack: remove the row-3 queen and continue from the square after it. |
| 39 | 3 | Row 3: square 4 is safe - place a queen, go to row 4. |
| 40 | 4 | Row 4: square 2 is safe - place a queen, go to row 5. |
| 41 | 4 | No safe square in row 5 - backtrack: remove the row-4 queen and continue from the square after it. |
| 42 | 3 | No safe square in row 4 - backtrack: remove the row-3 queen and continue from the square after it. |
| 43 | 2 | No 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. |
| 44 | 1 | Row 2 has no squares left - backtrack again: remove the row-1 queen and continue from the square after it. |
| 45 | 1 | Row 1: square 2 is safe - place a queen, go to row 2. |
| 46 | 2 | Row 2: square 4 is safe - place a queen, go to row 3. |
| 47 | 3 | Row 3: square 1 is safe - place a queen, go to row 4. |
| 48 | 4 | Row 4: square 3 is safe - place a queen, go to row 5. |
| 49 | 5 | Row 5: square 5 is safe - place a queen, go to row 6. |
| 50 | 5 | No safe square in row 6 - backtrack: remove the row-5 queen and continue from the square after it. |
| 51 | 4 | No safe square in row 5 - backtrack: remove the row-4 queen and continue from the square after it. |
| 52 | 3 | No safe square in row 4 - backtrack: remove the row-3 queen and continue from the square after it. |
| 53 | 3 | Row 3: square 6 is safe - place a queen, go to row 4. |
| 54 | 4 | Row 4: square 1 is safe - place a queen, go to row 5. |
| 55 | 5 | Row 5: square 3 is safe - place a queen, go to row 6. |
| 56 | 6 | Row 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
| Algorithm | Best | Average | Worst | Space | Stable |
|---|---|---|---|---|---|
| N-Queens (Backtracking)this page | O(n!) | O(n!) | O(n!) | O(n) | - |
| Depth-First Search | O(V + E) | O(V + E) | O(V + E) | O(V) | - |
| Trie (Prefix Tree) | O(m) | O(m) | O(m) | O(n·m) | - |
| Binary Search | O(1) | O(log n) | O(log n) | O(1) | - |