题目描述:
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。
示例:
- 输入:n = 4
输出:[[".Q…","…Q",“Q…”,"…Q."],["…Q.",“Q…”,"…Q",".Q…"]]
解释:如上图所示,4 皇后问题存在两个不同的解法。 - 输入:n = 1
输出:[[“Q”]]
思路:
列举出所有皇后可能摆放的情况,然后看是否是合法的,这样复杂度过高,因为可能的情况随着n呈现指数增长。
剪枝→一行一行的添加皇后,下一行不能和之前的行相同,而且为了保证不能相互攻击,发现下完一个棋子之后,他的对角线上的格子都呈现出一个特点就是,撇的话就是横纵坐标之后是相同的,捺的话横纵坐标相减的值是相同的,所以可以利用set来保证,下一行添加的时候,横纵坐标不在set中,具体的代码如下:
class Solution(object):
def solveNQueens(self, n):
"""
:type n: int
:rtype: List[List[str]]
"""
self.result = []
self.slove(0, n, [], [], [], [])
self.pattern_res = []
self.pattern_result(n)
return self.pattern_res
def slove(self, level, n, col, pie, na, cur_state):
if level == n:
self.result.append(cur_state)
return
for i in range(n):
if i not in col and i+level not in pie and i-level not in na:
col.append(i)
pie.append(i + level)
na.append(i - level)
self.slove(level+1, n, col, pie, na, cur_state+[i])
col.pop()
pie.pop()
na.pop()
def pattern_result(self, n):
for i in range(len(self.result)):
num = self.result[i]
pattern = []
for q in range(n):
str = ''
for i in range(n):
if num[q] != i:
str += '.'
else:
str += 'Q'
pattern.append(str)
self.pattern_res.append(pattern)
这里需要注意的是:
一个list.append()之后的返回值是一个null,这个操作是inplace的会使list值变化但是返回值不是list本身而是null,所以不能把list.append加入到递归函数的参数直接调用,可以像上面的代码的方式,也可以采用这样的方式:
self.put_queens(level+1, col+[i], pie+[i+level], na+[i-level], n, cur_state+[i])
采用+的方式,会返回一个新的地址空间,这样去作为递归函数的调用也是可以的,更推荐这种。
而且需要注意cur_state用来保存结果也不能用append,不然inplace,保存的结果又消失了!!!
复杂度分析:
时间复杂度:O(N!),其中 N是皇后数量。
空间复杂度:O(N)