LeetCode51. N 皇后 | 刷题打卡

152 阅读2分钟

LeetCode从低效到高效,点击

一、题目描述:

题目要求

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。 给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。 每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。

来源:力扣(LeetCode)链接

示例

输入:n = 4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]

二、思路分析:

非常有名的N皇后问题,隐隐约约记得之前写过八皇后,其中最不好写的就是判断这个位置能不能放皇后,如果每次放皇后都需要做很多次判断,那无疑是超时的。N皇后问题要求横、竖、左斜、右斜都不能相遇,一般来说都是从第一行到第N行遍历,那就没有横相遇的问题了,左斜与右斜的判断是最难处理的。 如何将左斜右斜的信息更密集的存储起来是这道题的主要问题,通过下图可以看出图中左斜与右斜共有(n1)21=7(n-1)*2-1=7条,其中右斜特征为x1y1=x2y2x_1-y_1=x_2-y_2,使用特征确定斜线编号,值范围是[3,3][-3,3],使用时需要对编号平移,保证从0开始;左斜相交的特征为x1+y1=x2+y2x_1+y_1=x_2+y_2,正好是从0开始的,这样就是用三个特征数组标记了竖、左斜、右斜的情况。

r.png

三、AC 代码:

// 8 ms	7.7 MB
vector<string> &vector2string(vector<int> &queens,vector<string> &vs,int n){
    for(int i=0;i<n;i++){
        string s = string(n,'.');
        s[queens[i]] = 'Q';
        vs.push_back(s);
    }
    return vs;
}

// clo:竖线是否存在  l左斜,r右斜,out:输出数组,搜索xindex坐标
void backtrack(vector<bool> &clo,vector<bool> &l,vector<bool> &r,vector<vector<string>> &out,int xindex,vector<int> &queens){
    // 如果这里采用先判断后放入的策略,调用者就需要使用多点dfs的策略,太麻烦了
    int n = clo.size();
    if(xindex == n){
        // 搜索完了
        vector<string> board;
        out.emplace_back(vector2string(queens,board,n));
    }
    // 搜索 (xindex,i)位置
    for(int i=0;i<n;i++){
        // 这里要判断三个坐标 clo l r
        int lvalue = xindex+i;
        int rvalue = i-xindex+(n-1);
        if(clo[i]||l[lvalue]||r[rvalue]){
            continue;
        }
        clo[i] = true;
        l[lvalue] = true;
        r[rvalue] = true;
        queens[xindex] = i;
        backtrack(clo,l,r,out,xindex+1,queens);
        clo[i] = false;
        l[lvalue] = false;
        r[rvalue] = false;
    }
}

vector<vector<string>> solveNQueens(int n) {
    vector<bool> column(n,false);
    vector<bool> l(2*n-1,false);
    vector<bool> r(2*n-1,false);
    vector<int> queens(n,0);
    vector<vector<string>> out;
    backtrack(column,l,r,out,0,queens);
    return out;
}

四、总结:

仔细观察题目特性,压缩判断条件,本地使用AddressSanitizer,报错信息会好看很多。

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情