題目描述:給定整數 n,回傳 n 皇后問題的不同解法數量。在 n×n 棋盤上放置 n 個皇后,使得任意兩個皇后不在同一行、同一列或同一對角線上。
解題思路:使用回溯法逐行放置皇后(每行恰好放一個)。為了快速判斷某一列是否被佔用,使用三個整數作為位元集合:
cols:記錄哪些列已被佔用。diag1:記錄哪些主對角線(/,行 + 列相同)已被佔用。diag2:記錄哪些副對角線(\,行 - 列相同)已被佔用。在第 row 行嘗試每一列 col:若對應位元均為 0(未被攻擊),則放置皇后,設定三個位元集合的對應位,遞迴至下一行,完成後清除位元(回溯)。當 row == n 時代表成功放置 n 個皇后,計數器加一。此法利用位元運算使每次合法性檢查為 O(1),整體效率遠優於逐格掃描。
時間複雜度:O(n!) — 第一行有 n 個選擇,第二行最多 n-1 個,依此類推,上界為 n!;實際因對角線剪枝而更少。
空間複雜度:O(n) — 遞迴深度為 n(每行一層),位元集合使用 O(1) 額外空間,無需儲存棋盤。
1. Initialize count = 0.
2. Call backtrack(row=0, cols=0, diag1=0, diag2=0).
3. In backtrack(row, cols, diag1, diag2):
a. If row == n: increment count and return.
b. For col from 0 to n-1:
- Compute d1 = row + col, d2 = row - col + n - 1.
- If bit col in cols is set, skip.
- If bit d1 in diag1 is set, skip.
- If bit d2 in diag2 is set, skip.
- Set bits: cols |= (1<<col), diag1 |= (1<<d1), diag2 |= (1<<d2).
- Recurse: backtrack(row+1, cols, diag1, diag2).
- Unset bits (backtrack).
4. Return count.方法一:位元操作最佳化回溯(Gosper's Hack)
直接計算每行所有可用列的位元遮罩(available = ~(cols | diag1 | diag2) & fullMask),再用 pos = available & (-available) 逐個取出最低位元,避免顯式 for 迴圈。時間複雜度同為 O(n!),但常數因子更小,實際速度更快,常用於競程解法。
方法二:標準回溯 + 陣列標記
用三個 boolean 陣列 col_used[n]、diag1_used[2n]、diag2_used[2n] 代替位元集合,邏輯相同但較易理解。時間複雜度 O(n!),空間複雜度 O(n)。適合初學者理解回溯框架後再進階到位元版本。