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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值