leetcode 51. N-Queens

本文介绍了如何解决LeetCode上的N-Queens问题,这是一个经典的回溯算法问题。通过求解n皇后的一半解,并根据对称性生成完整的解集。
摘要由CSDN通过智能技术生成

The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.

Given an integer n, return all distinct solutions to the n-queens puzzle.

Each solution contains a distinct board configuration of the n-queens' placement, where 'Q' and '.' both indicate a queen and an empty space respectively.

Example:

Input: 4
Output: [
 [".Q..",  // Solution 1
  "...Q",
  "Q...",
  "..Q."],

 ["..Q.",  // Solution 2
  "Q...",
  "...Q",
  ".Q.."]
]
Explanation: There exist two distinct solutions to the 4-queens puzzle as shown above.

题目返回n皇后的所有解

经典的回溯问题。这里有一个可以优化的地方是n皇后的解总是有对称解。所以实际上只需要求解一半的解,然后对称生成另一半解。代码如下:

class Solution(object):
    def solveNQueens(self, n):
        """
        :type n: int
        :rtype: List[List[str]]
        """
        #特殊值解
        if n == 1:
            return [['Q']]
        if n <= 3:
            return []
        # 一般解
        rowTamps = [] # 缓存Q在不用Col的Row Str
        numsUsed = [False]*n # 用于快速检测是否在同一列
        for i in range(n):
            rowTamp = "." * i + "Q" + "." * (n - 1 - i)
            rowTamps.append(rowTamp)
        ret = []
        
        def checkQueens(queenPoss, last): # 检测第last个Q的位置是否和前面的Q是否冲突
            lastPos = queenPoss[last]
            for i in range(last):
                qPos = queenPoss[i]
                if abs(lastPos - qPos) == last - i: # 不在一条斜线
                    return False
            return True

        def getResultByQueenPoss(queenPos): #组装一个答案
            result = []
            for pos in queenPos:
                result.append(rowTamps[pos])
            return result

        def DFS(queenPoss, finishQueenNum, ret, queenPosLimit,numsUsed): # 回溯求解
            if finishQueenNum == n: # 添加解和对称解
                ret.append(getResultByQueenPoss(queenPoss))
                imageQueenPoss = []
                for pos in queenPoss:
                    imageQueenPoss.append(n-1-pos)
                ret.append(getResultByQueenPoss(imageQueenPoss))
                return
            for i in range(queenPosLimit[finishQueenNum]):
                if numsUsed[i] :
                    continue
                numsUsed[i] = True
                queenPoss[finishQueenNum] = i
                if checkQueens(queenPoss, finishQueenNum):
                    DFS(queenPoss, finishQueenNum + 1, ret, queenPosLimit,numsUsed)
                numsUsed[i] = False

        queenPoss = [0] * n
        queenPosLimit = [n] * n
        queenPosLimit[0] = n // 2
        DFS(queenPoss, 0, ret, queenPosLimit,numsUsed)

        if n % 2 == 1: # 当第一个皇后放在n//2 (中间时)剩余解同样是成对出现的
            queenPoss[0] = n // 2
            numsUsed[n//2] = True
            queenPosLimit[1] = n // 2
            DFS(queenPoss, 1, ret, queenPosLimit,numsUsed)

        return ret

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值