The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.
Given an integer n, return all distinct solutions to the n-queens puzzle.
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:
Input: 4
Output: [
[".Q..", // Solution 1
"...Q",
"Q...",
"..Q."],
["..Q.", // Solution 2
"Q...",
"...Q",
".Q.."]
]
Explanation: There exist two distinct solutions to the 4-queens puzzle as shown above.
题目返回n皇后的所有解
经典的回溯问题。这里有一个可以优化的地方是n皇后的解总是有对称解。所以实际上只需要求解一半的解,然后对称生成另一半解。代码如下:
class Solution(object):
def solveNQueens(self, n):
"""
:type n: int
:rtype: List[List[str]]
"""
#特殊值解
if n == 1:
return [['Q']]
if n <= 3:
return []
# 一般解
rowTamps = [] # 缓存Q在不用Col的Row Str
numsUsed = [False]*n # 用于快速检测是否在同一列
for i in range(n):
rowTamp = "." * i + "Q" + "." * (n - 1 - i)
rowTamps.append(rowTamp)
ret = []
def checkQueens(queenPoss, last): # 检测第last个Q的位置是否和前面的Q是否冲突
lastPos = queenPoss[last]
for i in range(last):
qPos = queenPoss[i]
if abs(lastPos - qPos) == last - i: # 不在一条斜线
return False
return True
def getResultByQueenPoss(queenPos): #组装一个答案
result = []
for pos in queenPos:
result.append(rowTamps[pos])
return result
def DFS(queenPoss, finishQueenNum, ret, queenPosLimit,numsUsed): # 回溯求解
if finishQueenNum == n: # 添加解和对称解
ret.append(getResultByQueenPoss(queenPoss))
imageQueenPoss = []
for pos in queenPoss:
imageQueenPoss.append(n-1-pos)
ret.append(getResultByQueenPoss(imageQueenPoss))
return
for i in range(queenPosLimit[finishQueenNum]):
if numsUsed[i] :
continue
numsUsed[i] = True
queenPoss[finishQueenNum] = i
if checkQueens(queenPoss, finishQueenNum):
DFS(queenPoss, finishQueenNum + 1, ret, queenPosLimit,numsUsed)
numsUsed[i] = False
queenPoss = [0] * n
queenPosLimit = [n] * n
queenPosLimit[0] = n // 2
DFS(queenPoss, 0, ret, queenPosLimit,numsUsed)
if n % 2 == 1: # 当第一个皇后放在n//2 (中间时)剩余解同样是成对出现的
queenPoss[0] = n // 2
numsUsed[n//2] = True
queenPosLimit[1] = n // 2
DFS(queenPoss, 1, ret, queenPosLimit,numsUsed)
return ret