N皇后之回溯算法小结

题目介绍:51. N皇后
先给出答案:

class Solution(object):
    def solveNQueens(self, n):
        """
        :type n: int
        :rtype: List[List[str]]
        使用最基础的回溯算法,决策树遍历
        """
        import copy
        
        if n == 0: return []
        res = []
        path = [['.' for _ in range(n)] for _ in range(n)]  # 申请列表类型变量,因为python字符串不能直接修改某个字符
        direction = [[-1, -1, -1, 0, 0, 1, 1, 1],
                     [-1, 0 ,1, -1, 1, -1, 0, 1]]  # 分别表示上下左右 左上 左下 右上 右下

        # 判断当前位置是否合法,此处可以优化,因为当前元素上方、左下角和右上角的元素不需要判断
        def can(i, j):
            for biger in range(1, n+1):  # 一层一层向8个方向扩展,像泛起的水花
                for k in range(8): 
                    nexti = i + direction[0][k]*biger
                    nextj = j + direction[1][k]*biger
                    if nexti >= 0 and nexti < n and nextj >= 0 and nextj < n:
                        if path[nexti][nextj] == 'Q':
                            return False
            return True

        # 判断第i层可以放置的所有位置(当前行的所有位置),i从0开始
        def back_track(path, i):
            # 结束条件
            if i == n:
                res.append(copy.deepcopy(path))  # 注意使用深拷贝
                return

            for j in range(n):  # 遍历当前层的所有选择
                if can(i, j) == False:  # 判断第i层的j位置是否合法,进行剪枝操作
                    continue
                path[i][j] = 'Q'  # 做选择
                back_track(path, i+1)  # 回溯
                path[i][j] = '.'  # 撤销选择

        back_track(path, 0)
        str_res = [[''.join(line) for line in m] for m in res]  # 转换格式
        return str_res

# s = Solution()
# print(s.solveNQueens(4))

# 小实验用于测试
# path = [['.', '.' , '.'], ['.', '.' , '.']]
# a = path[:][:]
# path[1][0] = 'O'
# print(a)
# a = '....'
# a[1] = 'o'
# print(a)
  • 回溯实际上是遍历决策树,通过遍历每一种情况,从而确定哪些路径符合要求,其中时间复杂度为O(n!),比如在不含重复元素的“全排列”中,共有n!种解。这也是回溯算法的⼀个特点,不像动态规划存在重叠⼦问题可以优化,回溯算法就是纯暴⼒穷举,复杂度⼀般都很⾼。
  • 基本代码流程
result = []
def backtrack(路径, 选择列表):
	if 满⾜结束条件:
		result.add(路径)
	return
	
for 选择 in 选择列表:
	做选择  # 对应树的前序遍历
	backtrack(路径, 选择列表)
	撤销选择  # 对应树的后续遍历

ps:前序遍历的代码在进⼊某⼀个树的节点之前的那个时间点执⾏,后序遍历代码在离开某个节点之后的那个时间点执⾏。我们要在递归之前做出选择,在递归之后撤销刚才的选择。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值