leetcode 51. N皇后(python)

在这里插入图片描述
题解:
对于本题,我们首先创建一个棋盘,利用数组实现:

    def solveNQueens(self, n):

    	grid = [['.'] * n for i in range(n)]#创建棋盘

    	queen = set()#存储皇后的位置索引

    	output = []#存储最后的结果


    	self.queenDFS(grid, 0, n,queen,output)

    	return output

本题利用回溯算法解决。
对于本题,关键点有三个,一个是回溯算法的递归(撤销);一个是判断放置位置是否合法;找到所有的可行解。(即找到所有的全排列)

对于第一个关键点:
首先看labuladong大神准备的回溯算法模版:

def backtrack(...):
    for 选择 in 选择列表:
        做选择
        backtrack(...)
        撤销选择

对于这个撤销操作,存在两种可能:

  1. 即在选择当前位置之后,如果当前位置不满足条件,需要撤销选择,即回溯的过程,就像一棵二叉树,走到一个结点的子结点后,再退回到父结点。
  2. 再找到当前一组解后的撤销操作,即把所有变量变换回初始的状态,为开始下一轮的遍历做准备;
    代码如下:
def queenDFS(self,grid,index,n,queen,output):

    	if index == n:
    		solution = []
    		for _, col in sorted(queen):

    			solution.append('.' * col + 'Q' + '.' * (n-col-1))

    		output.append(solution)

    	for i in range(n):

    		if(self.isQueenOk(grid,index,i)):
    			# print("####")

    			queen.add((index,i))#进行选择

    			grid[index][i] = 'Q'#进行选择


    			self.queenDFS(grid, index + 1, n,queen,output)

    			grid[index][i] = '.'#进行撤销
    			queen.remove((index,i))#进行撤销

判断放置的位置是否合法
因为是按行索引,所以我们只需要判断列,主对角线,副对角线是否符合要求。
其中主对角线位置等于当前位置的行减一,列减一。副对角线位置等于当前位置的行减一,列加一。
代码如下:

    def isQueenOk(self,grid,row,col):

    	#纵向合法性校验
    	for i in range(row):

    		if grid[i][col] == 'Q':

    			return False

    	#主对角线合法性校验
    	x = row - 1
    	y = col - 1
    	

    	while x >= 0 and y >= 0:

    		if grid[x][y] == 'Q':

    			return False
    		x -= 1
    		y -= 1


    	#副对角线合法性校验
    	x = row - 1
    	y = col + 1
    	


    	while x >= 0 and y < len(grid[0]):

    		if grid[x][y] == 'Q':

    			return False
    		x -= 1
    		y += 1


    	return True

总体代码如下:

class Solution:
    def solveNQueens(self, n):

    	grid = [['.'] * n for i in range(n)]

    	queen = set()

    	output = []
    	# print(grid)


    	self.queenDFS(grid, 0, n,queen,output)

    	return output






    def isQueenOk(self,grid,row,col):

    	#纵向合法性校验
    	for i in range(row):

    		if grid[i][col] == 'Q':

    			return False

    	#主对角线合法性校验
    	x = row - 1
    	y = col - 1
    	

    	while x >= 0 and y >= 0:

    		if grid[x][y] == 'Q':

    			return False
    		x -= 1
    		y -= 1


    	#副对角线合法性校验
    	x = row - 1
    	y = col + 1
    	


    	while x >= 0 and y < len(grid[0]):

    		if grid[x][y] == 'Q':

    			return False
    		x -= 1
    		y += 1


    	return True


    def queenDFS(self,grid,index,n,queen,output):

    	if index == n:
    		solution = []
    		for _, col in sorted(queen):

    			solution.append('.' * col + 'Q' + '.' * (n-col-1))

    		output.append(solution)



    	for i in range(n):

    		if(self.isQueenOk(grid,index,i)):
    			# print("####")

    			queen.add((index,i))

    			grid[index][i] = 'Q'


    			self.queenDFS(grid, index + 1, n,queen,output)

    			grid[index][i] = '.'
    			queen.remove((index,i))

总结:
认为本题的关键在于回溯算法的撤销操作,以及四个方向的判断;认真理解回溯算法即可很好的求解本题。
本题是找到所有的可行解,如果是找到一组可行解,再找到之后直接进行return即可,不用进行后面的遍历。

参考:
https://leetcode-cn.com/problems/n-queens/solution/hui-su-suan-fa-xiang-jie-by-labuladong/
https://juejin.im/post/5accdb236fb9a028bb195562
https://www.jianshu.com/p/bb123944d3e5

发布了100 篇原创文章 · 获赞 3 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/cy_believ/article/details/104537229