按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n皇后问题研究的是如何将n个皇后放置在n×n的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数n,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的n 皇后问题的棋子放置方案,该方案中'Q'和'.'分别代表了皇后和空位。
思路
- 怎么回溯?
- 一行一行加皇后;
- 遍历每行能放的位置,即遍历所有可能性。
- 怎么判断能不能放?
- 不在同一行、不在同一列和不在斜对角。
- 怎么通过代码实现判断?
- 行:用递归树的高索引,自动增加;
- 列:借鉴全排列题目的做法,使用辅助数组q,
q[0...height-1]表示已经使用过的列,height以后的表示未使用的列。当该行已经确定一种位置,将其与q[i]交换; - 斜对角:只需判断左上角和右上角,左上角是
[r-1,c-1],右上角是[r-1,c+1],使用循环一个一个判断。
看题解学到的可能加速的方法
- 实现快速判断斜对角
- 左上角:同一斜线的行下标与列下标差相等;
- 右上角:同一斜线的行下标与列下标之和相等;
- 维护两个列表,判断当前位置的下标在这两个方向是否满足条件。
- 看力扣题解位运算
代码
class Solution(object):
def solveNQueens(self, n):
"""
:type n: int
:rtype: List[List[str]]
"""
q = [i for i in range(n)]
def dfs(height):
if height == n:
result.append(["".join(row) for row in res_i])
for i in range(height,n):
flag = 0
#左上角
r = height - 1
#注意当前情况的是q[i],不是q[height]
c = q[i] - 1
while r>=0 and c>=0 :
if res_i[r][c] == 'Q':
flag = 1
break
r = r-1
c = c-1
#右上角
r = height - 1
c = q[i] + 1
while r>=0 and c<n :
if res_i[r][c] == 'Q':
flag = 1
break
r = r-1
c = c+1
#判断斜对角是否符合条件
if flag == 1:
continue
#修改对应位置的值
res_i[height][q[i]] = 'Q'
#height后的是可以使用的列
q[i],q[height] = q[height],q[i]
#递归
dfs(height+1)
#撤销操作
q[i],q[height] = q[height],q[i]
res_i[height][q[i]] = '.'
res_i = [['.'] * n for _ in range(n)]
result = list()
dfs(0)
return result