11package com .thealgorithms .backtracking ;
22
33import java .util .ArrayList ;
4+ import java .util .HashSet ;
45import java .util .List ;
6+ import java .util .Set ;
57
68/**
79 * Problem statement: Given a N x N chess board. Return all arrangements in
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+ */
3542public final class NQueens {
43+
44+ // Store occupied rows for constant time safety check
45+ private static final Set <Integer > OCROWS = new HashSet <>();
46+
47+ // Store occupied main diagonals (row - column)
48+ private static final Set <Integer > OCDIAG = new HashSet <>();
49+
50+ // Store occupied anti-diagonals (row + columns)
51+ private static final Set <Integer > OCANTIDIAG = new HashSet <>();
52+
3653 private NQueens () {
3754 }
3855
@@ -43,10 +60,10 @@ 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 (" no way to place " + queens + " queens on board of size " + queens + "x" + queens );
5067 } else {
5168 System .out .println ("Arrangement for placing " + queens + " queens" );
5269 }
@@ -59,15 +76,15 @@ public static void placeQueens(final int queens) {
5976 /**
6077 * This is backtracking function which tries to place queen recursively
6178 *
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.
79+ * @param boardSize: size of chess board
80+ * @param solutions: this holds all possible arrangements
81+ * @param columns: columns[i] = rowId where queen is placed in ith column.
6582 * @param columnIndex: This is the column in which queen is being placed
6683 */
6784 private static void getSolution (int boardSize , List <List <String >> solutions , int [] columns , int columnIndex ) {
6885 if (columnIndex == boardSize ) {
6986 // this means that all queens have been placed
70- List <String > sol = new ArrayList <String >();
87+ List <String > sol = new ArrayList <>();
7188 for (int i = 0 ; i < boardSize ; i ++) {
7289 StringBuilder sb = new StringBuilder ();
7390 for (int j = 0 ; j < boardSize ; j ++) {
@@ -82,30 +99,29 @@ private static void getSolution(int boardSize, List<List<String>> solutions, int
8299 // This loop tries to place queen in a row one by one
83100 for (int rowIndex = 0 ; rowIndex < boardSize ; rowIndex ++) {
84101 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- }
92102
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 ;
103+ // Skip current position if row or diagonal is already occupied
104+ boolean isROp = OCROWS .contains (rowIndex );
105+
106+ boolean isDOp = OCDIAG .contains (rowIndex - columnIndex ) || OCANTIDIAG .contains (rowIndex + columnIndex );
107+
108+ if (isROp || isDOp ) {
109+ continue ;
107110 }
111+
112+ // Mark current row and diagonal as occupied
113+ OCROWS .add (rowIndex );
114+ OCDIAG .add (rowIndex - columnIndex );
115+ OCANTIDIAG .add (rowIndex + columnIndex );
116+
117+ // Move to the next column after placing current queen
118+ getSolution (boardSize , solutions , columns , columnIndex + 1 );
119+
120+ // Backtrack by removing current queen
121+
122+ OCROWS .remove (rowIndex );
123+ OCDIAG .remove (rowIndex - columnIndex );
124+ OCANTIDIAG .remove (rowIndex + columnIndex );
108125 }
109- return true ;
110126 }
111127}
0 commit comments