Leetcode算法题51 N-Queen解法代码及思路(C++)
原题:
算法结果:
个人思路
1.分析限定条件
限定条件是每行每列,每斜线不能有超过 1 个皇后,而且对于 n*n 的棋盘,要放入 n 个皇后,因此每行每列都必然有 1 个皇后,而且每行每列只有 1 个。
2.循环
由于每行每列必然都有 1 个皇后,我们可以从第 1 列开始,判断每列的皇后在第几行,来决定整个棋盘皇后的摆放。其中只需要注意判断新的皇后在不在之前皇后所在的行,以及在不在之前皇后所在的斜线上即可。(两处的代码分别见注释1,注释2)
3.列的变化
每次如果新的皇后没有和之前的行,斜线有冲突,那么列+1,
如果新的皇后和之前的行,斜线有冲突,那么行+1,也就是尝试将这个皇后摆到更高的行。
最后需要注意的是当皇后的行超过n(代码中行列从0开始,所以此处是超过n-1)时,将列-1,同时将该列的棋子上移一行,来尝试新的可能性。
4.时间复杂度
本题的时间复杂度必然比较高,因此尽可能降低每个棋子每次试探的判别次数。
最差情况下时间复杂度是O(nn)
使用了n=4,6,8,10进行了测试,
实际的时间复杂度大约在4*O(nn/2)
代码
class Solution {
public:
vector<vector<string>> solveNQueens(int n) {
int map[n]; //记录每列的皇后分别在第几行
vector<vector<string>> output;
vector<string> solution;
bool ld[n*2-1];//left diagonal左对角线
bool rd[n*2-1];//right diagonal右对角线
int i,j;
int o1,o2;
string temp = "";
for(i = 0; i< n; i ++)
{
temp +='.';
}
if(n==1)
{
solution.push_back("Q");
output.push_back(solution);
return output;
}
for(i = 0; i< n*2-1; i ++)
{
ld[i] = false;//false 表示该对角线未被使用
rd[i] = false;
}
map[0] = 0;
i = 0;
while(true)
{
if(map[i] == n)
{
i--;
if(i<0)
break;
ld[map[i]+i] = false;
rd[map[i]+n-1-i] = false;
map[i]++;
continue;
}
bool jump = false;
for(j = 0;j <i; j++) //注释1: 判断是否和之前已经摆放的皇后同行
{
if(map[i] == map[j])
{
map[i]++;
jump = true;
break;
}
}
if(jump)
continue;
if(ld[map[i]+i] | rd[map[i]+n-1-i]) //注释2: 判断所在的两条对角线是否被使用
{
map[i]++;
continue;
}
if(i == n-1)
{
solution.clear();
for(o1 = n-1; o1 >= 0 ; o1--)
{
string temp2 = temp;
for(o2 = 0; o2 < n ; o2++)
{
if(map[o2] == o1)
temp2[o2] = 'Q';
}
solution.push_back(temp2);
}
output.push_back(solution);
i--;
ld[map[i]+i] = false;
rd[map[i]+n-1-i] = false;
map[i]++;
continue;
}
ld[map[i]+i] = true;
rd[map[i]+n-1-i] = true;
i++;
map[i] = 0;
}
return output;
}
};