题解:N皇后问题

题目要求,每个皇后不能与其他皇后在同一行,同一列,同一对角线上。因此,我们可以从第一行一直往下搜索,如果符合条件,则将皇后放置在上面。

题目如下:

那么,条件应该如何设置呢?

题目分析

首先我们观察棋谱:

可以将上述棋谱抽象成二维数组的形式,那么每个格子对应的坐标为:

我们画一条 135°斜对角线,观察:

在这条对角线上的位置的下标的行列值之差, 是一个定值,为1
同时为了方便编写代码,使这样一个差值为非负数,我们加上棋盘的长度N;
那么这条对角线上是否有皇后就可以表示为:

if cdiag[n+x-y] ==True #True 表示为没有皇后

同理,画一条 45°斜对角线,观察

在这条对角线上的位置的下标的行列值之和, 是一个定值,为2
那么这条对角线上是否有皇后就可以表示为:

if diag[x+y] ==True #True 表示为没有皇后

所以我们判断这个位置是否应该放置皇后的时候, 只需要设立三个数组col(列), diag(正对角线), cdiag(负对角线);
然后合并判断列, 45°对角线, 135°对角线上是否有皇后即可

if(col[i]==True and diag[r+i]==True and cdiag[n+r-i]==True)  #True 表示为没有皇后

题解

有了上述分析后,现在只需要初始化棋盘,使用DFS进行遍历是否符合上述条件就可以了
首先初始化棋盘以及判断条件:

class Solution:
    def solveNQueens(self, n: int) -> List[List[str]]:
        res=[]
        init=[['.' for i in range(n)] for i in range(n)]
        diag=[True for i in range(2*n)]
        col=[True for i in range(n)]
        cdiag=[True for i in range(2*n)]
        dfs(0,n,init,diag,col,cdiag,res)
        return res

接下来用DFS来进行遍历是否符合条件

def dfs(r,n,map,diag,col,cdiag,res):
        if(r==n):
            red=[]
            for i in map:
                red.append("".join(i))
            res.append(red)
        for i in range(0,n):
            if(col[i]==True and diag[r+i]==True and cdiag[n+r-i]==True):
                map[r][i]='Q'
                col[i]=diag[r+i]=cdiag[n+r-i]=False
                dfs(r+1,n,map,diag,col,cdiag,res)
                map[r][i] = '.'   #如果路径不对,就退回
                col[i] = cdiag[n+r-i] = diag[r+i] = True

大功告成!

拓展

在此题的基础上,我们可以消灭第52题,N皇后Ⅱ

只改变一行代码,就能解决该题:

return len(res)

将返回值res改为返回res的长度即可