N-Queens⚓︎
Description⚓︎
The n-queens puzzle is the problem of placing n
queens on an n x n
chessboard such that no two queens attack each other.
Given an integer n
, return all distinct solutions to the n-queens puzzle. You may return the answer in any order.
Each solution contains a distinct board configuration of the n-queens' placement, where 'Q'
and '.'
both indicate a queen and an empty space, respectively.
Example 1:
- Input:
n = 4
- Output:
[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
- Explanation: There exist two distinct solutions to the
4
-queens puzzle as shown above
Example 2:
- Input: n = 1
- Output: [["Q"]]
Constraints:
1 <= n <= 9
Solution⚓︎
Way 1⚓︎
Way 2⚓︎
Understanding the Safe Spot Determination:
In the N-Queens problem, a spot (or cell) on the board is considered "safe" if no other queen can attack the queen placed on that spot. Note that a queen in chess can move vertically, horizontally, and diagonally over any number of unoccupied squares. Therefore, a spot is safe if:
- No Other Queen in the Same Column: Since a queen can attack any square in her column, we must ensure that no other queen is placed in the same column.
- No Other Queen in the Same Diagonals: A queen can also attack any square on the diagonals originating from her position. This includes both left and right diagonals.
To efficiently check these conditions, the solution uses three arrays: column
, lDiagonal
, and rDiagonal
.
column
Array: Tracks whether a column is occupied by a queen.lDiagonal
andrDiagonal
Arrays: Track the diagonals. Diagonals are a bit trickier to handle. Each diagonal can be uniquely identified by a particular property:- Right ( \(\searrow\) ) Diagonals: On these diagonals, the row index minus the column index (
row - column
) is constant. - Left ( \(\swarrow\) ) Diagonals: Here, the row index plus the column index (
row + column
) is constant.
- Right ( \(\searrow\) ) Diagonals: On these diagonals, the row index minus the column index (
However, to use arrays efficiently and avoid negative indices for left diagonals, an offset is added. That's why for right diagonals, we use sizeBoard - index + j
to keep indices positive and within the array bounds.
Execution of the Solution:
- Initialization: When
solveNQueens
is called, it initializes all necessary arrays and variables. Thepath
array is initialized to represent an empty N×N chessboard. - Recursive Backtracking: The function
backtracking
is called starting from the first row (index 0). - Placing a Queen: For each row, the algorithm iterates through each column (
j
) and checks if placing a queen there is safe:- It checks
column[j]
,lDiagonal[index + j]
, andrDiagonal[sizeBoard - index + j]
. If any of these aretrue
, it means the corresponding column or diagonal is already occupied by another queen, and it moves to the next column.
- It checks
- Marking the Board: If a safe spot is found, the algorithm places a queen there (
path[index][j] = 'Q'
) and marks the column and diagonals as occupied. - Recursion to Next Row: After placing a queen, the algorithm recursively calls
backtracking
for the next row (index + 1
). - Backtracking: If it turns out that no further queens can be placed, or after successfully placing all queens, the function backtracks:
- It removes the queen from the current cell (
path[index][j] = '.'
). - It unmarks the column and diagonals.
- The loop then continues to try the next column in the current row.
- It removes the queen from the current cell (
- Adding to Result: Once a queen is successfully placed in the last row (base case), the current board configuration (
path
) is added to the results (res
).
Complexity:
- Time Complexity: Worst-Case Time Complexity is \(O(N!)\)
- In the worst case, the algorithm tries to place a queen in each column of each row. The number of possibilities decreases with each level of recursion, leading to \(N!\) (factorial) as the upper bound.
- Space Complexity: Space Complexity is \(O(N)\)
- The space complexity is linear due to the storage of the board state and the recursive call stack. The board state requires \(O(N)\) space, and the maximum depth of the recursive call stack is \(N\).
Another way of writing: