N-Queens II — Hard Problem & Solution
Place n chess queens on an n x n board so that no two of them attack each other: no two queens may share a row, a column, or a diagonal (in either direction).
- Difficulty: Hard
- Topics: Bit Manipulation, Backtracking
- Asked at: Amazon, Google, Microsoft
- Time limit: 2 s
- Memory limit: 256 MB
- Languages: JavaScript, TypeScript, Python, Java, C++, C, C#, Go, Kotlin, Swift, Rust, PHP and Ruby
Problem statement
Place n chess queens on an n x n board so that no two of them attack each other: no two queens may share a row, a column, or a diagonal (in either direction).
Return the number of different placements. Two placements are different when some square holds a queen in one and not in the other — mirror images and rotations count separately.
Example 1
Input: n = 4
Output: 2
Explanation: The two placements put the queens in columns `[1,3,0,2]` and `[2,0,3,1]` of rows 0..3.
Example 2
Input: n = 1
Output: 1
Example 3
Input: n = 6
Output: 4
Constraints
1 <= n <= 9
How to solve N-Queens II
Place one queen per row and backtrack over the column choice. Bitmasks for the occupied columns and both diagonal directions make each "is this square free?" test a single AND.
Approach
- Let
full = (1 << n) - 1.solve(cols, d1, d2)returns the number of completions; whencols == full, every row has a queen, so return 1. - The free squares of the current row are
full & ~(cols | d1 | d2). - For each free bit
b(takefree & -free, then clear it), addsolve(cols | b, ((d1 | b) << 1) & full, (d2 | b) >> 1). - Return
solve(0, 0, 0).
Why it works
A queen in column c of the current row attacks column c - 1 (or c + 1) of the next row along its diagonals, and one further per row after that — shifting the diagonal masks by one bit per row tracks exactly those squares. So the search visits exactly the valid partial placements, and every complete one is counted once because each row's column is chosen once.
Complexity
- Time —
O(n!) in the worst case — far less in practice thanks to pruning - Space —
O(n) recursion depth
Pitfalls
- Shift the two diagonal masks in opposite directions.
- Mask the left-shifted diagonal (or the free set) with
full, or bits beyond the board look occupied or free. - n = 2 and n = 3 have no solution: the answer is 0, not an error.
Reference solution
Python
def totalNQueens(n: int) -> int:
full = (1 << n) - 1
def solve(cols, d1, d2):
if cols == full:
return 1
count = 0
avail = full & ~(cols | d1 | d2)
while avail:
bit = avail & -avail
avail ^= bit
count += solve(cols | bit, ((d1 | bit) << 1) & full, (d2 | bit) >> 1)
return count
return solve(0, 0, 0)JavaScript
var totalNQueens = function(n) {
var full = (1 << n) - 1;
var solve = function(cols, d1, d2) {
if (cols === full) return 1;
var count = 0;
var avail = full & ~(cols | d1 | d2);
while (avail !== 0) {
var bit = avail & -avail;
avail ^= bit;
count += solve(cols | bit, ((d1 | bit) << 1) & full, (d2 | bit) >> 1);
}
return count;
};
return solve(0, 0, 0);
};Also on the editorial tab: C, C#, C++, Go, Java, Kotlin, PHP, Ruby, Rust, Swift, TypeScript.
All 125 bit manipulation problems · the whole catalogue
Learn the technique: Bit Manipulation · Backtracking