The N-Queens problem asks: can you place N chess queens on an N×N board so that no two queens attack each other — meaning no two share a row, a column, or a diagonal? It's one of the most famous backtracking problems in computer science (the classic version uses an 8×8 board), and it's a great exercise for learning how to prune a search space instead of brute-forcing every possible arrangement.
The approach places one queen per row, working row by row. Before placing a queen in a column, it checks whether that column or either diagonal is already under attack from a queen placed in an earlier row. If the spot is safe, place the queen and recurse to the next row; if a full board of N rows is reached, a solution has been found. If no column in the current row is safe, backtrack to the previous row and try a different column there.
Python Program to Solve the N-Queens Problem Using Backtracking
def solve_n_queens(n):
board = [-1] * n # board[row] = column of the queen in that row
def is_safe(row, col):
for prev_row in range(row):
prev_col = board[prev_row]
same_col = prev_col == col
same_diagonal = abs(prev_col - col) == abs(prev_row - row)
if same_col or same_diagonal:
return False
return True
def backtrack(row):
if row == n:
return True # all N queens placed successfully
for col in range(n):
if is_safe(row, col):
board[row] = col
if backtrack(row + 1):
return True
board[row] = -1 # undo and try the next column
return False
if backtrack(0):
return board
return None
def print_board(board, n):
for row in range(n):
line = ["Q" if col == board[row] else "." for col in range(n)]
print(" ".join(line))
n = 8
solution = solve_n_queens(n)
if solution:
print_board(solution, n)
else:
print(f"No solution exists for N = {n}")
Output:
Q . . . . . . .
. . . . Q . . .
. . . . . . . Q
. . . . . Q . .
. . Q . . . . .
. . . . . . Q .
. Q . . . . . .
. . . Q . . . .
This version stops at the first valid solution, which is enough for most interview settings — to find all distinct solutions (there are 92 for the classic 8×8 board), remove the early `return True` and instead append a copy of `board` to a results list every time `row == n` is reached, then keep backtracking. The key optimization here versus brute force is that `is_safe` prunes an entire branch of the search tree the moment a conflict is found, rather than generating every possible arrangement of N queens and checking each one afterward — that brute-force approach would need to examine up to C(N², N) placements, while backtracking with pruning explores a dramatically smaller fraction of that space in practice.
