又是一道DFS排列经典题。这题用visited[]还不够,要专门用一个isValid()函数来确保没有列冲突和两个对角线冲突。
注意:
1) string的初始化:
string dotStr(n, ‘.’);
vector solString(n, dotStr); //good string initialization code!
代码如下:
class Solution {
public:
/*
* @param n: The number of queens
* @return: All distinct solutions
*/
vector<vector<string>> solveNQueens(int n) {
vector<vector<string>> results;
vector<int> sol;
if (n == 0) {
results.push_back(vector<string>());
return results;
}
helper(n, 0, sol, results);
return results;
}
private:
bool isValid(vector<int> &sol, int col) {
int row = sol.size();
for (int rowId = 0; rowId < sol.size(); ++rowId) {
if (sol[rowId] == col)
return false;
if (sol[rowId] + rowId == col + row)
return false;
if (sol[rowId] - rowId == col - row)
return false;
}
return true;
}
void helper(int n, int index, vector<int>&sol, vector<vector<string>> &results) {
if (index == n) {
string dotStr(n, '.');
vector<string> solString(n, dotStr); //good string initialization code!
for (auto i : sol) {
solString[i][sol[i]] = 'Q';
}
results.push_back(solString);
return;
}
for (int i = 0; i < n; ++i) {
if (isValid(sol, i)) {
sol.push_back(i);
helper(n, index + 1, sol, results);
sol.pop_back();
}
}
}
};
写成下面这样也可以。这样for loop里面用sol[index] = i; 就可以了,不用push_back又pop_back。
class Solution {
public:
/*
* @param n: The number of queens
* @return: All distinct solutions
*/
vector<vector<string>> solveNQueens(int n) {
vector<vector<string>> results;
vector<int> sol(n, 0);
if (n == 0) {
results.push_back(vector<string>());
return results;
}
helper(n, 0, sol, results);
return results;
}
private:
bool isValid(vector<int> &sol, int col, int index) {
int row = index; //sol.size();
for (int rowId = 0; rowId < index; ++rowId) {
if (sol[rowId] == col)
return false;
if (sol[rowId] + rowId == col + row)
return false;
if (sol[rowId] - rowId == col - row)
return false;
}
return true;
}
void helper(int n, int index, vector<int>&sol, vector<vector<string>> &results) {
if (index == n) {
string dotStr(n, '.');
vector<string> solString(n, dotStr); //good string initialization code!
for (auto i : sol) {
solString[i][sol[i]] = 'Q';
}
results.push_back(solString);
return;
}
for (int i = 0; i < n; ++i) {
if (isValid(sol, i, index)) {
sol[index] = i;
helper(n, index + 1, sol, results);
}
}
}
};
另外,这题还可以优化。主要是isValid()的复杂度可以从O(n)降到O(1)。我们可以设3个长度为n…2n的数组,分别表示列,对角线和反对角线是否有冲突。反对角线可以用i+j,即如果i行j列有Queen,则a[i+j]=1。对角线则要用i-j或j-i。但这里有个问题因为i-j或j-i可能为负。一个技巧就是用i-j+n,这样就没有负数了。