51. N 皇后

127 阅读2分钟

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。

每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。

题目链接leetcode-cn.com/problems/n-…  

解题思路:递归

还是那句话,遇事不决先递归

先来分析一下问题

先来分析一个给出的4x4的实例

我们把每一个位置放置Q的情况做分析

很明显,首先每一行只能放一个Q,而且放完以后会在后面的每一行产生3个不能放置Q的点(产生的点可以超出棋盘)如图所示:蓝色的线为该点向左产生的不能放置的Q点,黄色向右,绿色向下

首先我们定义一个变量,记录放置Q的点

path = [path1,path2,...]

那我们就可以针对这个不能放置Q的点定义一个变量pos = [[],[],[]],里面由三个数产生,分别是向下的向左的和向右的我们定义为l,r,m ,由于这个m是和path重复的这个变量我们就重新定义为

所有蓝线覆盖的点 l = [l1,l2,...]

所有黄线覆盖的点 r = [r1,r2,...]

所有线覆盖的点 total = [path + l + r]

这样我们就可以针对每个位置写判断的代码了,如果total里面没有该位置,我们就可以进入下一步,生成新的下一个行的l,r,total,

设当前执行的的行数为第n行,总行数为N

ln = [path1-(n-1),path2-(n-2),...]

rn = [path1+(n-1),path2+(n-2),...]

pathn = [path1,paht2,...]

我们就可以从第n行的0,开始判断

for i in range(N):
	if i in total:
    	continue#没有空位就继续,
        #有空位就进坑,使用这个位置进行下一行的递归
        faction ([pathn]+[i],[ln]+[i],[rn]+[i]

算上上面的逻辑,我们就有这样的递归函数

def recursion(path, l , r):
            if len(path) == n:#最后一行结束,如果是棋盘能放下最后一个
                #这里要放一个记录下当前解法的代码
                return
            l = [i-1 for i in l]
            r = [i+1 for i in r]
            total = l+r+path
            for i in range(n):
                if i in total:
                    continue
                recursion(path+[i], l+[i], r+[i])

再根据题目需求,把path改成题目需求的输出格式,整个题目的回答就是这样的


class Solution(object):
    def solveNQueens(self, n):
        """
        :type n: int
        :rtype: List[List[str]]
        """
        self.res = []
        def trans(path):
            return ['.'*i + 'Q' + '.'*(len(path)-1-i) for i in path]
        def recursion(path, l , r):
            if len(path) == n:
                self.res.append(trans(path))
                return
            l = [i-1 for i in l]
            r = [i+1 for i in r]
            total = l+r+path
            for i in range(n):
                if i in total:
                    continue
                recursion(path+[i], l+[i], r+[i])
        recursion([], [], [])
        return self.res