Every Way to Place N Non-Attacking Queens on a Board
Solve this ProblemTest Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ n ≤ 8 - ◆
A queen attacks any square sharing its row, column, or either diagonal - ◆
Each board is returned as n strings of length n, using 'Q' for a queen and '.' for an empty square - ◆
Results are returned sorted (each board compared row by row) for a stable, checkable answer
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
Approach & Solutions
Brute Force — Re-Scan Every Placed Queen at Each Attempt
BrutePlace one queen per row. Before trying a column at the current row, walk every queen placed at an earlier row and check directly whether it shares that column or either diagonal — an O(row) scan repeated for every column tried, at every row. This is correct (only column-per-row placements avoid same-row conflicts by construction), but re-deriving "is this column or diagonal already taken" by re-examining every earlier queen, over and over, is exactly the same fact recomputed many times over the course of the search.
O(n! · n)O(n)1class Solution {
2 public String[][] nonAttackingQueenBoards(int n) {
3 List<String[]> result = new ArrayList<>();
4 int[] queenCol = new int[n];
5 backtrack(n, 0, queenCol, result);
6 result.sort((a, b) -> {
7 for (int i = 0; i < a.length; i++) {
8 int cmp = a[i].compareTo(b[i]);
9 if (cmp != 0) return cmp;
10 }
11 return 0;
12 });
13 return result.toArray(new String[0][]);
14 }
15
16 private void backtrack(int n, int row, int[] queenCol, List<String[]> result) {
17 if (row == n) {
18 result.add(buildBoard(n, queenCol));
19 return;
20 }
21 for (int c = 0; c < n; c++) {
22 if (isSafe(row, c, queenCol)) {
23 queenCol[row] = c;
24 backtrack(n, row + 1, queenCol, result);
25 }
26 }
27 }
28
29 private boolean isSafe(int row, int col, int[] queenCol) {
30 for (int r = 0; r < row; r++) {
31 int c = queenCol[r];
32 if (c == col || Math.abs(c - col) == Math.abs(r - row)) {
33 return false;
34 }
35 }
36 return true;
37 }
38
39 private String[] buildBoard(int n, int[] queenCol) {
40 String[] board = new String[n];
41 for (int r = 0; r < n; r++) {
42 StringBuilder sb = new StringBuilder();
43 for (int c = 0; c < n; c++) sb.append(c == queenCol[r] ? 'Q' : '.');
44 board[r] = sb.toString();
45 }
46 return board;
47 }
48}Optimal — Track Used Columns and Diagonals Directly
OptimalInstead of re-examining every earlier queen to answer "is this column or diagonal free," maintain that fact directly: one set for occupied columns, and one each for the two diagonal directions (identified by row−col and row+col, which stay constant along a diagonal). Placing a queen adds one entry to each set; removing one on backtrack deletes them again. Checking whether a column or diagonal is available becomes a single O(1) lookup instead of an O(row) walk over every previously placed queen.
O(n!)O(n)1class Solution {
2 public String[][] nonAttackingQueenBoards(int n) {
3 List<String[]> result = new ArrayList<>();
4 Set<Integer> cols = new HashSet<>();
5 Set<Integer> diag1 = new HashSet<>();
6 Set<Integer> diag2 = new HashSet<>();
7 int[] queenCol = new int[n];
8 backtrack(n, 0, cols, diag1, diag2, queenCol, result);
9 result.sort((a, b) -> {
10 for (int i = 0; i < a.length; i++) {
11 int cmp = a[i].compareTo(b[i]);
12 if (cmp != 0) return cmp;
13 }
14 return 0;
15 });
16 return result.toArray(new String[0][]);
17 }
18
19 private void backtrack(int n, int row, Set<Integer> cols, Set<Integer> diag1, Set<Integer> diag2, int[] queenCol, List<String[]> result) {
20 if (row == n) {
21 result.add(buildBoard(n, queenCol));
22 return;
23 }
24 for (int c = 0; c < n; c++) {
25 if (cols.contains(c) || diag1.contains(row - c) || diag2.contains(row + c)) continue;
26 cols.add(c);
27 diag1.add(row - c);
28 diag2.add(row + c);
29 queenCol[row] = c;
30 backtrack(n, row + 1, cols, diag1, diag2, queenCol, result);
31 cols.remove(c);
32 diag1.remove(row - c);
33 diag2.remove(row + c);
34 }
35 }
36
37 private String[] buildBoard(int n, int[] queenCol) {
38 String[] board = new String[n];
39 for (int r = 0; r < n; r++) {
40 StringBuilder sb = new StringBuilder();
41 for (int c = 0; c < n; c++) sb.append(c == queenCol[r] ? 'Q' : '.');
42 board[r] = sb.toString();
43 }
44 return board;
45 }
46}