Skip to content

Commit 6005788

Browse files
committed
Optimized NQueens implementation using hashing
1 parent 2616e09 commit 6005788

1 file changed

Lines changed: 44 additions & 28 deletions

File tree

src/main/java/com/thealgorithms/backtracking/NQueens.java

Lines changed: 44 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import java.util.ArrayList;
44
import java.util.List;
5+
import java.util.HashSet;
6+
import java.util.Set;
57

68
/**
79
* Problem statement: Given a N x N chess board. Return all arrangements in
@@ -32,7 +34,22 @@
3234
* queen is not placed safely. If there is no such way then return an empty list
3335
* as solution
3436
*/
37+
38+
/*
39+
* Time Complexity: O(N!)
40+
* space Complexity: O(N)
41+
*/
3542
public final class NQueens {
43+
44+
// Store occupied rows for constant time safety check
45+
private static final Set<Integer> occupiedRows = new HashSet<>();
46+
47+
// Store occupied main diagonals (row - column)
48+
private static final Set<Integer> occupiedDiagonals = new HashSet<>();
49+
50+
// Store occupied anti-diagonals (row + columns)
51+
private static final Set<Integer> occupiedAntiDiagonals = new HashSet<>();
52+
3653
private NQueens() {
3754
}
3855

@@ -43,10 +60,11 @@ public static List<List<String>> getNQueensArrangements(int queens) {
4360
}
4461

4562
public static void placeQueens(final int queens) {
46-
List<List<String>> arrangements = new ArrayList<List<String>>();
63+
List<List<String>> arrangements = new ArrayList<>();
4764
getSolution(queens, arrangements, new int[queens], 0);
4865
if (arrangements.isEmpty()) {
49-
System.out.println("There is no way to place " + queens + " queens on board of size " + queens + "x" + queens);
66+
System.out.println(
67+
"There is no way to place " + queens + " queens on board of size " + queens + "x" + queens);
5068
} else {
5169
System.out.println("Arrangement for placing " + queens + " queens");
5270
}
@@ -59,15 +77,15 @@ public static void placeQueens(final int queens) {
5977
/**
6078
* This is backtracking function which tries to place queen recursively
6179
*
62-
* @param boardSize: size of chess board
63-
* @param solutions: this holds all possible arrangements
64-
* @param columns: columns[i] = rowId where queen is placed in ith column.
80+
* @param boardSize: size of chess board
81+
* @param solutions: this holds all possible arrangements
82+
* @param columns: columns[i] = rowId where queen is placed in ith column.
6583
* @param columnIndex: This is the column in which queen is being placed
6684
*/
6785
private static void getSolution(int boardSize, List<List<String>> solutions, int[] columns, int columnIndex) {
6886
if (columnIndex == boardSize) {
6987
// this means that all queens have been placed
70-
List<String> sol = new ArrayList<String>();
88+
List<String> sol = new ArrayList<>();
7189
for (int i = 0; i < boardSize; i++) {
7290
StringBuilder sb = new StringBuilder();
7391
for (int j = 0; j < boardSize; j++) {
@@ -82,30 +100,28 @@ private static void getSolution(int boardSize, List<List<String>> solutions, int
82100
// This loop tries to place queen in a row one by one
83101
for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
84102
columns[columnIndex] = rowIndex;
85-
if (isPlacedCorrectly(columns, rowIndex, columnIndex)) {
86-
// If queen is placed successfully at rowIndex in column=columnIndex then try
87-
// placing queen in next column
88-
getSolution(boardSize, solutions, columns, columnIndex + 1);
89-
}
90-
}
91-
}
92103

93-
/**
94-
* This function checks if queen can be placed at row = rowIndex in column =
95-
* columnIndex safely
96-
*
97-
* @param columns: columns[i] = rowId where queen is placed in ith column.
98-
* @param rowIndex: row in which queen has to be placed
99-
* @param columnIndex: column in which queen is being placed
100-
* @return true: if queen can be placed safely false: otherwise
101-
*/
102-
private static boolean isPlacedCorrectly(int[] columns, int rowIndex, int columnIndex) {
103-
for (int i = 0; i < columnIndex; i++) {
104-
int diff = Math.abs(columns[i] - rowIndex);
105-
if (diff == 0 || columnIndex - i == diff) {
106-
return false;
104+
// Skip current position if row or diagonal is already occupied
105+
if (occupiedRows.contains(rowIndex)
106+
|| occupiedDiagonals.contains(rowIndex - columnIndex)
107+
|| occupiedAntiDiagonals.contains(rowIndex + columnIndex)) {
108+
continue;
107109
}
110+
111+
// Mark current row and diagonal as occupied
112+
occupiedRows.add(rowIndex);
113+
occupiedDiagonals.add(rowIndex - columnIndex);
114+
occupiedAntiDiagonals.add(rowIndex + columnIndex);
115+
116+
// Move to the next column after placing current queen
117+
getSolution(boardSize, solutions, columns, columnIndex + 1);
118+
119+
// Backtrack by removing current queen
120+
121+
occupiedRows.remove(rowIndex);
122+
occupiedDiagonals.remove(rowIndex - columnIndex);
123+
occupiedAntiDiagonals.remove(rowIndex + columnIndex);
108124
}
109-
return true;
110125
}
126+
111127
}

0 commit comments

Comments
 (0)