【LeetCode】103.N-Queens

题目描述(Hard)

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.

题目链接

https://leetcode.com/problems/n-queens/description/

Example 1:

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.

算法分析

设置一个数组vector<int>C(n, 0), C[i]表示第i行皇后所在的列编号,即在位置(i, C[i])上放了一个皇后,这样用一个一维数组就能记录整个棋盘。

方法一:对当前行,每次逐列扫描,判断所在位置是否放置皇后(前面的行的皇后是否冲突),判断条件,对第i行: 1.是否在同一列C[i]==col;2.是否在同一对角线abs(row-i)==abs(col-C[i]),即两点不构成正方形,就不在一条对角线上。时间复杂度O(n!*n),空间复杂度O(n)

方法二:记录皇后已经占据的列,占据的主对角线、副对角线,对N×N的棋盘,主对角线和副对角线各2N-1条。对第row行,第i列数据,其所在主对角线位置为row-j+N-1,其所在副对角线的位置为row+j。时间复杂度O(n!),空间复杂度O(n)

提交代码(方法一):

class Solution {
public:
    vector<vector<string>> solveNQueens(int n) {
        vector<vector<string>> result;
        vector<int> C(n, -1);
        dfs(result, C, 0);
        return result;
    }
    
    void dfs(vector<vector<string>> &result, vector<int> &C, int row) {
        const int N = C.size();
        if (row == N) {
            vector<string> solution;
            for (int i = 0; i < N; ++i) {
                string S(N, '.');
                S[C[i]] = 'Q';
                solution.push_back(S);
            }
            result.push_back(solution);
            return;
        }
        
        // 逐列扫描
        for (int i = 0; i < N; ++i) {
            if (!isValid(C, row, i)) continue;
            C[row] = i; 
            dfs(result, C, row + 1);
            C[row] = -1;
        }
    }
    
    bool isValid(vector<int>& C, int row, int col) {
        for (int i = 0; i < row; ++i) {
            // 如果在相同列
            if (C[i] == col) return false;
            // 在对角线上
            if (abs(row - i) == abs(col - C[i])) return false;
        }
        
        return true;
    }
    
};

提交代码(方法二):

class Solution {
public:
    vector<vector<string>> solveNQueens(int n) {
        columns = vector<bool>(n, false);
        main_diag = vector<bool>(2 * n - 1, false);
        anti_diag = vector<bool>(2 * n - 1, false);
        vector<vector<string>> result;
        vector<int> C(n, -1);
        dfs(result, C, 0);
        return result;
    }
private:
    vector<bool> columns;
    vector<bool> main_diag;
    vector<bool> anti_diag;
    void dfs(vector<vector<string>> &result, vector<int> &C, int row) {
        const int N = C.size();
        if (row == N) {
            vector<string> solution;
            for (int i = 0; i < N; ++i) {
                string S(N, '.');
                S[C[i]] = 'Q';
                solution.push_back(S);
            }
            result.push_back(solution);
            return;
        }
        
        // 逐列扫描
        for (int i = 0; i < N; ++i) {
            bool valid =  !columns[i] && !main_diag[row - i + N - 1]
                && !anti_diag[row + i];
            if (!valid) continue;
            columns[i] = main_diag[row - i + N - 1] 
                = anti_diag[row + i] = true;
            C[row] = i; 
            dfs(result, C, row + 1);
            C[row] = -1;
            columns[i] = main_diag[row - i + N - 1] 
                = anti_diag[row + i] = false;
        }
    }
};

猜你喜欢

转载自blog.csdn.net/ansizhong9191/article/details/83272599