1.题目
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
示例 1:
输入:n = 4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
解释:如上图所示,4 皇后问题存在两个不同的解法。
示例 2:
输入:n = 1
输出:[["Q"]]
提示:
1 <= n <= 9
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/n-queens
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2.个人题解
时间复杂度:小于n!
空间复杂度:n2
class Solution:
def solveNqueen(self, n: int): # :表示参数类型
solve = []
a = set()
b = set()
c = set()
bool_Queen = [[False] * n] * n
def addresult(n :int):
result = []
for i in range(n):
temp = ["Q" if bool_Queen[i][j] else "." for j in range(n)]
result.append("".join(temp)) # "".join()生成的是字符串
return result
def backtrack(row: int):
if row == n:
final = addresult(n)
solve.append(final) # 列表不存在本地变量的说法
else:
for i in range(n):
if i in a or i - row in b or i + row in c:
continue
else:
# 列表不像Numpy 无法对切片赋值 但可以从列表推导式的方向去思考
# bool_Queen[row][:] = False 报错
bool_Queen[row] = [False] * n # 对每一行进行初始化
bool_Queen[row][i] = True
a.add(i)
b.add(i - row)
c.add(i + row)
backtrack(row + 1) # 回溯法递归
a.remove(i) # 清除记忆
b.remove(i - row)
c.remove(i + row)
backtrack(0)
return solve
debug = Solution()
a = debug.solveNqueen(4)
for i, solve in enumerate(a):
print("第%d种情况:" % i, solve, "\n")
3.官方题解
回朔法,实则是深度优先遍历,别忘了回朔时的初始化
### https://leetcode-cn.com/problems/n-queens/solution/nhuang-hou-by-leetcode-solution/
### 回朔法(递归), 官方题解
class Solution:
def solveNQueens(self, n: int): # :表示参数类型
def generateBoard():
board = list()
for i in range(n):
row[queens[i]] = "Q"
board.append("".join(row)) # 针对str的操作,可以将“”中的值插入每个元素之间
row[queens[i]] = "." # 还原
return board
def backtrack(row: int):
if row == n: # 这里是走完一圈后记录结果 也是递归出口 # row == n 相当于行超出了,比如总共n行 这里表示的意思是递归到第n+1行,所以退出
board = generateBoard()
solutions.append(board)
else:
for i in range(n):
if i in columns or row - i in diagonal1 or row + i in diagonal2:
continue
queens[row] = i # quneens这个不用像下面一样remove,因为这相当于一个temp 只当有正确结果输出的时候他才会起作用
columns.add(i)
diagonal1.add(row - i)
diagonal2.add(row + i)
backtrack(row + 1) # 这里体现回溯, 本来我遇到了个循环的瓶颈:如何进行N次循环以保证每行的多种情况不丢失,这个方法完美结局,
# 对每一行的每种情况往下层递归,然后完成后回到这层时候,通过下面的remove将之前记录的信息删除,回到完成这种情况后的初态
columns.remove(i) # 这个三个要remove因为会对判断操作带来影响
diagonal1.remove(row - i)
diagonal2.remove(row + i)
solutions = list()
queens = [-1] * n # 注意这里和下面的row不需要二维的数组 因为函数体中的queens[row] = i 是记录每一行皇后的索引
columns = set() # 集合
diagonal1 = set()
diagonal2 = set()
row = ["."] * n
backtrack(0) # 我们需要查找的是索引为0 -- n-1 行
return solutions