LeetCode从低效到高效,点击
一、题目描述:
题目要求
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。 给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。 每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
来源:力扣(LeetCode)链接
示例
输入:n = 4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
二、思路分析:
非常有名的N皇后问题,隐隐约约记得之前写过八皇后,其中最不好写的就是判断这个位置能不能放皇后,如果每次放皇后都需要做很多次判断,那无疑是超时的。N皇后问题要求横、竖、左斜、右斜都不能相遇,一般来说都是从第一行到第N行遍历,那就没有横相遇的问题了,左斜与右斜的判断是最难处理的。 如何将左斜右斜的信息更密集的存储起来是这道题的主要问题,通过下图可以看出图中左斜与右斜共有条,其中右斜特征为,使用特征确定斜线编号,值范围是,使用时需要对编号平移,保证从0开始;左斜相交的特征为,正好是从0开始的,这样就是用三个特征数组标记了竖、左斜、右斜的情况。
三、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 春招闯关活动」, 点击查看 活动详情