題目描述:在 n×n 的棋盤上放置 n 個皇后,使得任意兩個皇后都不在同一行、同一列或同一對角線上。回傳所有不同的解法,每個解法以字串陣列表示('Q' 代表皇后,'.' 代表空格)。
解題思路:使用逐行回溯的方法,每一行恰好放一個皇后(因為同行不能有兩個皇后)。從第 0 行開始,嘗試在每一列放置皇后;若該位置合法,則移到下一行繼續;若所有行都放完,記錄一個解。
衝突檢查(O(1)):用三個集合追蹤已佔用的位置:
cols:已有皇后的列編號diag1:已有皇后的 (row - col) 值(主對角線方向,同一對角線上的格子 row-col 相同)diag2:已有皇后的 (row + col) 值(副對角線方向,同一對角線上的格子 row+col 相同)對於第 row 行第 col 列,若 col、row-col、row+col 均不在對應集合中,則該位置合法。
建構解:回溯完成後,將 n 個皇后的列位置轉換為字串陣列格式。
時間複雜度:O(n!) — 第一行有 n 個選擇,第二行至多 n-1 個(同列排除),依此類推,總共最多 n! 種放置方式。實際上對角線衝突會大幅剪枝,遠少於 n!,但 O(n!) 是上界。此外,每次找到解時建構棋盤需 O(n²)。
空間複雜度:O(n) — 三個集合各最多儲存 n 個元素;queenCol 陣列長度為 n;遞迴堆疊深度為 n。不計輸出結果所用的空間。
1. Initialize queenCol[0..n-1] = -1, empty sets: cols, diag1, diag2
2. Define backtrack(row):
a. If row == n:
- Build board: for each row r, set board[r][queenCol[r]] = 'Q', rest = '.'
- Add board to result, return
b. For col from 0 to n-1:
- If col in cols OR (row-col) in diag1 OR (row+col) in diag2: skip
- Place queen: queenCol[row]=col, add col/row-col/row+col to sets
- Recurse: backtrack(row + 1)
- Remove queen: queenCol[row]=-1, remove from sets
3. Call backtrack(0)
4. Return result位元遮罩回溯 O(n!):用三個整數的位元位(bitmask)代替集合追蹤衝突,利用位元運算(&、|、~)以更低的常數因子進行衝突檢查,是競技程式設計中常見的優化。時間複雜度相同,但實際執行速度更快。
對稱性剪枝:N 皇后問題具有關於中心軸的對稱性,只需搜尋前 ⌈n/2⌉ 個列的起始位置,再對稱產生另一半解。可將搜尋空間減半,但實作較複雜且程式可讀性降低,通常作為競賽優化技巧而非面試解法。