题目:n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
来源:https://leetcode-cn.com/problems/n-queens/
法一: 自己的代码 时间超过了百分之90
思路: 参照官方的解法,用处理list的回溯框架实现了一遍,关键是要满足题中的四个条件,水平的是用for循环遍历的,不会出现重复,两个斜向的用p和q来实现,竖直方向用cols来记录,这四个条件实际上就是剪枝条件.
class Solution: def solveNQueens(self, n: int): results = [] def backtrack(row=-1,col=0): # 回溯终止条件,如果到最后一行了,说明找到一个解了,存储 if row == n-1: solution = [] for _, col in sorted(queens): solution.append('.' * col + 'Q' + '.' * (n - col - 1)) results.append(solution) return row += 1 for col in range(n): # 如果等于0,说明可以放, # if这儿就是剪枝条件 if cols[col] + p[col+row] + q[col-row] == 0: # 放置一个皇后 queens.add((row,col)) # 这里cols的作用实际上是为了记录竖直方向上是否偶皇后, # p,q为了记录两个斜方向上是否有皇后 # 水平方向用for循环遍历,每次回溯结束后就置0,所以一定没有皇后 # 且由于这些都是可变对象,回溯函数每次调用结束后,值更改后的值仍然存在,故需要回溯函数后面加上置0的程序 # 而 row 和 col是不变对象,回溯函数每次调用结束后,会恢复调用前的值 cols[col] = 1 p[col+row] = 1 q[col-row] = 1 backtrack(row,col) # 回溯函数结束后,取出刚才放的皇后,继续for循环,判断下一个位置 queens.remove((row,col)) cols[col] = 0 p[col + row] = 0 q[col - row] = 0 cols = [0] * n # p记录主对角线方向的,q记录副对角线方向的 # p,q是通过画图观察出来的,引入p,q是为了区分放置皇后后斜线方向上不能再放置皇后 p = [0] * (2*n - 1) q = [0] * (2*n - 1) # 因为list不能append pop 元组,故这里用set queens = set() backtrack() return results if __name__ == '__main__': duixiang = Solution() ww = duixiang.solveNQueens(4) print('结果是:', ww)
法二: 官方的解法,思路非常清晰用了多个函数实现了模块化
# 官网python代码 class Solution: def solveNQueens(self, n: int): def could_place(row, col): return not (cols[col] + hill_diagonals[row - col] + dale_diagonals[row + col]) def place_queen(row, col): queens.add((row, col)) cols[col] = 1 hill_diagonals[row - col] = 1 dale_diagonals[row + col] = 1 def remove_queen(row, col): queens.remove((row, col)) cols[col] = 0 hill_diagonals[row - col] = 0 dale_diagonals[row + col] = 0 def add_solution(): solution = [] for _, col in sorted(queens): solution.append('.' * col + 'Q' + '.' * (n - col - 1)) output.append(solution) def backtrack(row=0): for col in range(n): if could_place(row, col): place_queen(row, col) if row + 1 == n: add_solution() else: backtrack(row + 1) # 执行这个的目的是回溯函数结束时,返回调用前的状态 remove_queen(row, col) cols = [0] * n hill_diagonals = [0] * (2 * n - 1) dale_diagonals = [0] * (2 * n - 1) queens = set() output = [] backtrack() return output if __name__ == '__main__': duixiang = Solution() ww = duixiang.solveNQueens(4) print('结果是:', ww)