LeetCode 51. N-Queens--回溯法 pyhon,java,c++解法

LeetCode 51. N-Queens


LeetCode题解专栏:LeetCode题解
我做的所有的LeetCode的题目都放在这个专栏里,大部分题目Java和Python的解法都有。


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皇后问题,可以用回溯法解决
注意:Python和Java的解法是一样的,我看不懂C++的解法
大佬的python解法如下:

class Solution:
    def solveNQueens(self, n: int) -> List[List[str]]:
        def DFS(queens, xy_dif, xy_sum):
            p = len(queens) # p is the index of row
            if p == n:
                result.append(queens)
                return None
            for q in range(n): # q is the index of col 
                # queens stores those used cols, for example, [0,2,4,1] means these cols have been used
                # xy_dif is the diagonal 1
                # xy_sum is the diagonal 2
                if q not in queens and p - q not in xy_dif and p + q not in xy_sum:
                    DFS(queens + [q], xy_dif + [p - q], xy_sum + [p + q])

        result = []
        DFS([], [], [])
        return [["." * i + "Q" + "." * (n - i - 1) for i in sol] for sol in result]

大佬的java解法如下:

//use backtracking algorithm to try out the positions
//for every level, there are n options to place. try them as in a small for loop
//from that level, go down, for each path, choose the next level node. check whether it's valid or not. if valid, then go on backtracking. (use a tmplist to store location info) 
//if not valid, return.
//return condition is that it reached the final level and all queens placed
//question: what does it mean that two queens don't attach each other? 
//怎么来看是否valid, 如何标记 每当加一个数字进去,相应的三个方向用数组来记录 mark下
//One puts a queen on the board and that immediately excludes one column, one row and two diagonals for the further queens placement.
//go back if not valid

class Solution {
    //boolean array to track whether it can be placed or not.
    //when one queen is placed on board, board[level][i], its column, its two diagonals are occupied.
    boolean[] col;
    boolean[] D45;
    boolean[] D135; //这个D135的好难想  
    public List<List<String>> solveNQueens(int n) {
        //create a grid and fill it. 
        char[][] board = new char[n][n];
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                board[i][j] = '.'; 
            }
        }
        col = new boolean[n];
        D45 = new boolean[2 * n];
        D135 = new boolean[2 * n]; //default to false. meaning can place. true means occupied/can't place. 
        List<List<String>> res = new ArrayList<>();
        if(n <= 0) return res; 
        backtrack(board, res, 0, n);
        return res;         
    }
    
    public void backtrack(char[][] board, List<List<String>> res, int level, int n) {
        //if(level > n) return; 
        if(level == n) {
            addSolution(res, board); 
            return; 
        }
        for(int i = 0; i < n; i++) {
            //if(!canPlace(board[level][i])) return;
            if(col[i] || D45[level + i] || D135[i - level + n - 1]) continue;  //确实是应该continue, return直接出去了, 这在for loop里面呢 
            //45度角的是 row + col. 
            //135是col - row. 
            //otherwise, continue
            board[level][i] = 'Q'; 
            col[i] = true;
            D45[level + i] = true;
            D135[i - level + n - 1] = true; 
            
            backtrack(board, res, level + 1, n);
            
            board[level][i] = '.'; //复原 unmark for other routes. 
            col[i] = false;
            D45[level + i] = false;
            D135[i - level + n - 1] = false;         
        }              
    }
    
    public void addSolution(List<List<String>> res, char[][]board) {
        List<String> tmp = new ArrayList<>(); 
        for(char[] level : board) {
            tmp.add(String.valueOf(level)); //charArray to string. String.valueOf()
        }
        res.add(tmp); 
    }
    
}

大佬的c++解法如下:

class Solution {
public:
    vector<vector<string>> solveNQueens(int n) {
        vector<vector<string>> res;
        vector<string> solution(n,std::string(n,'.'));
        
        solve(res,solution,n,0,0,0);
        return res;
    }
    void solve(vector<vector<string>> &res,vector<string> &solution,int n,int row, int ld ,int rd){
        if(((1<<n)-1)==row){
            res.push_back(solution);
            return;
        }
        int D= ((1<<n)-1)&(~(row|rd|ld));
        while(D){
            int bit=D&(~D+1);
            solution[rowcount(row)][n-colcount(bit)]='Q';
            solve(res,solution,n,row|bit,(ld|bit)<<1,(rd|bit)>>1);
            solution[rowcount(row)][n-colcount(bit)]='.';
            D=D^bit;
        }
    }
    int rowcount(int row){
        int cnt=0;
        while(row){
            cnt+=row&0x1;
            row>>=1;
        }
        return cnt;
    }
    int colcount(int col){
        int cnt=0;
        while(col){
            cnt++;
            col>>=1;
        }
        return cnt;
    }
};

正常的C++解法如下:

class Solution {
public:
    std::vector<std::vector<std::string> > solveNQueens(int n) {
        std::vector<std::vector<std::string> > res;
        std::vector<std::string> nQueens(n, std::string(n, '.'));
        std::vector<int> flag_col(n, 1), flag_45(2 * n - 1, 1), flag_135(2 * n - 1, 1);
        solveNQueens(res, nQueens, flag_col, flag_45, flag_135, 0, n);
        return res;
    }
private:
    void solveNQueens(std::vector<std::vector<std::string> > &res, std::vector<std::string> &nQueens, std::vector<int> &flag_col, std::vector<int> &flag_45, std::vector<int> &flag_135, int row, int &n) {
        if (row == n) {
            res.push_back(nQueens);
            return;
        }
        for (int col = 0; col != n; ++col)
            if (flag_col[col] && flag_45[row + col] && flag_135[n - 1 + col - row]) {
                flag_col[col] = flag_45[row + col] = flag_135[n - 1 + col - row] = 0;
                nQueens[row][col] = 'Q';
                solveNQueens(res, nQueens, flag_col, flag_45, flag_135, row + 1, n);
                nQueens[row][col] = '.';
                flag_col[col] = flag_45[row + col] = flag_135[n - 1 + col - row] = 1;
            }
    }
};

猜你喜欢

转载自blog.csdn.net/zhangpeterx/article/details/89341283