N皇后问题是把N个皇后放在一个N×N棋盘上,使皇后之间不会互相攻击。
给出一个整数n,返回n皇后问题的所有摆放方案
例如:
4皇后问题有两种摆放方案
[".Q..", // 解法 1 "...Q", "Q...", "..Q."], ["..Q.", // 解法 2 "Q...", "...Q", ".Q.."] ]
package go.jacob.day0610.chapter8_recursion; import java.util.ArrayList; /** * 著名n皇后问题 * 题目解析: * n个皇后摆放在n*n的棋盘格中,使得横、竖和两个对角线方向均不会同时出现两个皇后 * <p> * 解题思路: * 由于需要在n*n的棋盘格中放入n个皇后,就必须每一行放一个 * 否则就会出现一行有两个皇后的情况,会发生冲突。 * 那么就可以递归的解决每一行问题 * 最核心的问题是:如何能快速判断不合法的情况,即快速剪枝 * 同行或同列的冲突可以简单用一个数组来考虑,难点是两条对角线 * 对角线条数2*n-1 * 左对角线:坐标x+y是一个唯一定值 x+y 范围为0到2*n-2 * 右对角线:坐标x-y是一个唯一定值 x-y+n-1 范围为0到2*n-2 */ public class Solution { private ArrayList<String[]> res; private boolean[] col;//列 private boolean[] dia1;//左对角线 private boolean[] dia2;//右对角线 public ArrayList<String[]> solveNQueens(int n) { res = new ArrayList<String[]>(); if (n == 0) return res; col = new boolean[n]; dia1 = new boolean[2 * n - 1]; dia2 = new boolean[2 * n - 1]; putQueen(n, 0, new ArrayList<Integer>()); return res; } //尝试在一个n皇后问题中,摆放第index行的皇后位置,row存放的是每一行皇后存放的下标 private void putQueen(int n, int index, ArrayList<Integer> row) { if (index == n) { res.add(generateBoard(n, row)); return; } for (int i = 0; i < n; i++) { //判断能否将第index行的皇后摆放在第i列 if (!col[i] && !dia1[index + i] && !dia2[index - i + n - 1]) { col[i] = true; dia1[index + i] = true; dia2[index - i + n - 1] = true; row.add(i); putQueen(n, index + 1, row); row.remove(row.size() - 1); col[i] = false; dia1[index + i] = false; dia2[index - i + n - 1] = false; } } } private String[] generateBoard(int n, ArrayList<Integer> row) { String[] list = new String[n]; for (int i = 0; i < n; i++) { StringBuilder s = new StringBuilder(); for (int j = 0; j < n; j++) { if (j == row.get(i)) s.append("Q"); else s.append("."); } list[i] = s.toString(); } return list; } }
import java.util.ArrayList; import java.util.Arrays; public class Solution {ArrayList<String[]> ret = new ArrayList<>(); public ArrayList<String[]> solveNQueens(int n) { if(n <= 0) return ret; int[] array = new int[n]; helper(array, 0); return ret; }
//A[i] = j 表示 i 行 j 列 上放置了一个皇后
public boolean check(int[] array,int k){
//验证新加入的第k行是否可以
for(int i = 0;i < k; i++){
if(array[i] == array[k] || k - i == Math.abs(array[k] - array[i])) return false;
}
return true;
}
public void helper(int[] array,int k){
if(k == array.length){
String[] s = new String[array.length];
for(int i = 0;i < array.length;i++){
char[] ca = new char[array.length];
Arrays.fill(ca, '.');
ca[array[i]] = 'Q';
s[i] = new String(ca);
}
ret.add(s);
return;
}
for(int i = 0;i< array.length;i++){
array[k] = i;
if(check(array,k)){
helper(array, k + 1);
}
}
}
}
import java.util.ArrayList; public class Solution { static ArrayList<String[]> result; public ArrayList<String[]> solveNQueens(int n) { result = new ArrayList<>(); if(n <= 0) return result; // cols[i]代表第i个皇后所在的列 int[] cols = new int[n]; for(int i = 0; i < n; i++){ // 将第1个queen放置好 cols[0] = i; Strategy(cols, 1); } return result; } // 递归放置皇后 public void Strategy(int[] cols, int row){ // 放到了最后一列,结束 if(row == cols.length){ // 这里其实最好用StringBuffer String[] str = new String[cols.length]; for(int i = 0; i < str.length; i++){ str[i] = ""; for(int j = 0; j < str.length; j++){ if(j == cols[i]) str[i] += "Q"; else str[i] += "."; } } result.add(str); return; } // 试凑放置皇后的位置 for(int i = 0; i < cols.length; i++){ if(isValid(cols, row, i)){ cols[row] = i; Strategy(cols, row + 1); } } } // 判断在row行col列放置的皇后是否合法 public boolean isValid(int[] cols, int row, int col){ if(cols == null) return false; // 与之前皇后在同一列或者斜对角线,即不合法 for(int i = 0; i < row; i++){ if(cols[i] == col || Math.abs(cols[i] - col) == Math.abs(row - i)) return false; } return true; } }
/*运行时间:151ms
占用内存:15344k
*/ import java.util.ArrayList; public class Solution { public ArrayList<String[]> solveNQueens(int n) { ArrayList<String[]> r = new ArrayList<String[]>(); char[][] cur = new char[n][n]; for(int i = 0;i < n;i++){ for(int j = 0;j < n;j++) cur[i][j] = '.'; } dfs(r,cur,n,0); return r; } private void dfs(ArrayList<String[]> r,char[][] cur,int n,int row){ if(n == row){ String[] s = new String[n]; for(int i = 0;i < n;i++){ String tmp = new String(cur[i]); s[i] = tmp; } r.add(s); return; } for(int i = 0;i < n;i++){ if(isValid(cur,n,row,i)){ cur[row][i] = 'Q'; dfs(r,cur,n,row+1); cur[row][i] = '.'; } } } private boolean isValid(char[][] cur,int n,int row,int col){ //从第一行往下面依次放入queue,所以不用考虑下面未放入的,只考虑上面已存在的 //排除行 for(int i = 0;i < col;i++){ if(cur[row][i] == 'Q') return false; } //排出列 for(int i = 0;i < row;i++){ if(cur[i][col] == 'Q') return false; } //排除斜线 for(int i = row - 1,j = col - 1;i >= 0 && j >= 0;i--,j--){ if(cur[i][j] == 'Q') return false; } // 排除反斜线 for(int i = row - 1,j = col + 1;i >= 0 && j< n;i--,j++){ if(cur[i][j] == 'Q') return false; } return true; } }
class Solution { public: vector<vector<string> > solveNQueens(int n) { vector<string> board(n, string(n, '.')); DFS(0, board, n); return sols_; } private: vector<vector<string>> sols_; int cols_, diag1_, diag2_; bool available(int x, int y, int n) { return !(cols_ & 1 << x || diag1_ & 1 << (x + y) || diag2_ & 1 << (n - 1 + x - y)); } void putBoard(vector<string>& board, int x, int y, int n, bool flag) { board[y][x] = flag ? 'Q' : '.'; if (flag) { cols_ |= 1 << x; diag1_ |= 1 << (x + y); diag2_ |= 1 << (n - 1 + x - y); } else { cols_ -= 1 << x; diag1_ -= 1 << (x + y); diag2_ -= 1 << (n - 1 + x - y); } } void DFS(int y, vector<string>& board, int n) { if (y == n) { sols_.emplace_back(board); return; } for (int x = 0; x < n; ++x) { if (not available(x, y, n)) continue; putBoard(board, x, y, n, true); DFS(y + 1, board, n); putBoard(board, x, y, n, false); } } };
class Solution { public: vector<vector<string> > res; vector<int> A; int n; vector<vector<string> > solveNQueens(int n) { this->n=n; A.resize(n); findNQueens(0); return res; } bool check(int row,int col){ for(int i=0;i<row;i++){ if(A[i]==col||abs(A[i]-col)==abs(i-row)){ return false; } } return true; } void findNQueens(int k){ if(k==n){ vector<string> v(n,string(n,'.')); for(int i=0;i<n;i++){ v[i][A[i]]='Q'; } res.push_back(v); return; } for(int i=0;i<n;i++){ if(check(k,i)){ A[k]=i; findNQueens(k+1); } } } };
class Solution { public: vector<vector<string>> res; vector<vector<string>> solveNQueens(int n) { vector<string> curStr; vector<vector<bool>> flag(n, vector<bool>(n, true)); nQueens(n, 0, curStr, flag); return res; } void nQueens(int &n, int cur, vector<string> &curStr, vector<vector<bool>> flag){ if(curStr.size() == n){ res.push_back(curStr); return ; } for(int i = 0; i < n; i ++ ){ if(!flag[cur][i]){ continue; } else{ curStr.push_back(cStr(i,n)); nQueens(n, cur+1, curStr, flagTrans(flag, cur, i)); curStr.pop_back(); } } } vector<vector<bool>> flagTrans(vector<vector<bool>> flag, int i, int j){ int len = flag.size(); for(int k = 0; k < len; k++ ) flag[k][j] = false; int token1 = i, token2 = j; while(max(++token1,++token2) < len){ flag[token1][token2] = false; } token1 = i, token2 = j; while(min(--token1,--token2) >= 0){ flag[token1][token2] = false; } token1 = i, token2 = j; while(++token1<len && --token2>=0){ flag[token1][token2] = false; } token1 = i, token2 = j; while(--token1>=0 && ++token2<len){ flag[token1][token2] = false; } return flag; } string cStr(int index,int &n){ string s; for(int i= 0; i<n ;i++){ if(i == index) s+='Q'; else s+='.'; } return s; } };
class Solution {
public:
vector<vector<string>> solveNQueens(int n) {
vector<vector<string>> res;
vector<string> board(n, string(n, '.'));
vector<int> pos(n, 1);
vector<int> flag1(n + n - 1, 1); // ↘️的对角线
vector<int> flag2(n + n - 1, 1); // ↙️的对角线
backTrack(res, board, pos, flag1, flag2, 0);
return res;
}
void backTrack(vector<vector<string>> &res, vector<string> &board, vector<int> &pos, vector<int> &flag1, vector<int>& flag2, int idx) {
if(idx == pos.size()) {
res.push_back(board);
return;
}
for(int i = 0; i < pos.size(); ++i) {
// 不能出现同一列
if(pos[i] == 0)
continue;
// 不能出现在同一条斜线上
int n = i - idx, m = i + idx;
n += (pos.size() - 1);
if(flag1[n] == 0 || flag2[m] == 0)
continue;
pos[i] = 0;
board[idx][i] = 'Q';
flag1[n] = 0;
flag2[m] = 0;
backTrack(res, board, pos, flag1, flag2, idx + 1);
pos[i] = 1;
board[idx][i] = '.';
flag1[n] = 1;
flag2[m] = 1;
}
}
};
public ArrayList<String[]> solveNQueens(int n) { ArrayList<String[]> result = new ArrayList<String[]>(); boolean col[] = new boolean[n+1]; //列 boolean tip1[] = new boolean[n*2+1]; //右对角斜线 2~2n boolean tip2[] = new boolean[n*2+1]; //左对角斜线 2~2n Stack<String> stack = new Stack<String>(); nQueens(n, 1, col, tip1, tip2, result, stack); return result; } public void nQueens(int n, int cou, boolean col[], boolean tip1[], boolean tip2[], ArrayList<String[]> result, Stack<String> stack){ if(cou > n){ String a[] = new String[n]; stack.toArray(a); result.add(a); return; } for(int i=1; i<=n; i++){ if(!col[i] && !tip1[cou+i] && !tip2[n-cou+1+i]){ stack.push(genString(i, n)); col[i] = true; tip1[cou+i] = true; tip2[n-cou+1+i] = true; nQueens(n, cou+1, col, tip1, tip2, result, stack); col[i] = false; tip1[cou+i] = false; tip2[n-cou+1+i] = false; stack.pop(); } } } public String genString(int i, int len){ char chs[] = new char[len]; Arrays.fill(chs, '.'); chs[i-1] = 'Q'; return new String(chs); }
import java.util.*; public class Solution { public ArrayList<String[]> solveNQueens(int n) { ArrayList<String[]> res = new ArrayList<String[]>(); helper(n, 0, new int[n], res);//利用一个数组保存Q的位置信息,数组下标表示行,数组元素表示放置Q的列 return res; } private void helper(int n, int row, int[] columnForRow, ArrayList<String[]> res) { if (row == n) {//row=n表示已经找到了数组,将数组转化为结果即可。 String[] item = new String[n]; for (int i = 0; i < n; i++) { StringBuilder strRow = new StringBuilder(); for (int j = 0; j < n; j++) { if (columnForRow[i] == j)//在数组记录的位置上写入Q strRow.append('Q'); else strRow.append('.');//在其他所有位置上写入. } item[i] = strRow.toString(); } res.add(item); return; } for (int i = 0; i < n; i++) { columnForRow[row] = i; if (check(row, columnForRow)) { helper(n, row + 1, columnForRow, res); } } } private boolean check(int row, int[] columnForRow) { for (int i = 0; i < row; i++) { if (columnForRow[row] == columnForRow[i] || Math.abs(columnForRow[row] - columnForRow[i]) == row - i) return false; } return true; } }
class Solution(object): def solve(self, n, i, m, l0, l1, l2): if i == n: return [m[:]] res = [] for j in range(n): if j not in l0 and i + j not in l1 and j - i not in l2: m.append(j) l0[j] = 1 l1[i + j] = 1 l2[j - i] = 1 res.extend(self.solve(n, i + 1, m, l0, l1, l2)) m.pop() l0.pop(j) l1.pop(i + j) l2.pop(j - i) return res def solveNQueens(self, n): res = self.solve(n, 0, [], {}, {}, {}) solutions = [] for r in res: solution = [] for rr in r: line = "" for i in range(n): line += "." if i != rr else "Q" solution.append(line) solutions.append(solution) return solutions
class Solution { public: vector<vector<string> > solveNQueens(int n) { string str; for(int i=0;i<n;i++) str.push_back('.'); vector<string> vec; int a[n]; for(int i=0;i<n;i++) vec.push_back(str); vector<vector<string> > res; Back(n,0,res,vec,a); return res; } void Back(int n,int t,vector<vector<string> > &res,vector<string> vec,int *a) { if(n == t) { res.push_back(vec); return; } for(int i=0;i<n;i++) { a[t] = i; if(Push(t,a)) { vec[t][i] = 'Q'; Back(n,t+1,res,vec,a); vec[t][i] = '.'; } } } bool Push(int m,int a[]) { bool flag = true; for(int i=0;i<m;i++) { if(a[i] == a[m] || abs(a[m]-a[i]) == (m-i)) { flag = false; break; } } return flag; } };
import java.util.*; public class Solution { ArrayList<String[]> list = new ArrayList<String[]>(); public ArrayList<String[]> solveNQueens(int n) { char[][] res = new char[n][n]; for(char[] chs : res) Arrays.fill(chs, '.'); int[] cols = new int[n]; int[] slash1 = new int[2*n-1]; int[] slash2 = new int[2*n-1]; DFS(res, n, 0, cols, slash1, slash2); return list; } public void DFS(char[][] res, int n, int cur, int cols[], int slash1[], int slash2[]) { if(cur == n) { String[] s = new String[n]; for(int i=0; i<n; i++) s[i] = new String(res[i]); list.add(s); } for(int i=0; i<n; i++) { if(cols[i] != 1 && slash1[cur + i] != 1 && slash2[n-1-cur+i] != 1) { cols[i] = 1; slash1[cur + i] = 1; slash2[n-1-cur+i] = 1; res[cur][i] = 'Q'; DFS(res, n, cur+1, cols, slash1, slash2); cols[i] = 0; slash1[cur + i] = 0; slash2[n-1-cur+i] = 0; res[cur][i] = '.'; } } } }
};
class Solution { public: vector > solveNQueens(int n) { vector > res; vector solution; vector occupiedCol(n, -1); solveNQueens(0, n, solution,res, occupiedCol); return res; } private: void solveNQueens(int row, int n, vector& solution, vector >& res, vector& occupiedCol) { if(row == n){res.push_back(solution);return;} for(int i=0; i < n; i++) { string s(n, '.'); s[i] = 'Q'; occupiedCol[row] = i; solution.push_back(s); if(ifValid(occupiedCol, row, i)) { solveNQueens(row+1, n, solution, res, occupiedCol); } solution.pop_back(); occupiedCol[row] = -1; } } bool ifValid(vector& occupiedCols, int i, int j) { int len = occupiedCols.size(); for(int m = 0; m < i; m++) {//检查前面的行 int k = occupiedCols[m]; if(j == k || abs(j-k) == abs(i-m))//若前面的行皇后所在的列与j相等或者与(i,j)在同一对角线上 return false; } return true; } };
//递归回溯 vector<vector<string> > solveNQueens(int n) { string str; for(int i=0;i<n;i++) str.push_back('.'); vector<string> vec; int *arr=new int[n]; for(int i=0;i<n;i++) vec.push_back(str); vector<vector<string>> result; goahead(n,0,result,vec,arr); return result; } void goahead(int n,int t,vector<vector<string>> &res,vector<string> vec,int *arr){ if(n==t){ res.push_back(vec); return; } for(int i=0;i<n;i++){ arr[t]=i; if(push(t,arr)){ vec[t][i]='Q'; goahead(n,t+1,res,vec,arr); vec[t][i]='.'; } } } bool push(int m,int *arr){ bool flag=true; for(int i=0;i<m;i++){ if(arr[i]==arr[m] ||abs(arr[m]-arr[i])==(m-i)){ flag=false; break; } } return flag; }
class Solution { public: //tmp[i]表示第i行的Q在哪一列 void findSolution(int n,vector<vector<int> >&pos, vector<int>&tmp){ if(tmp.size()==n) { pos.push_back(tmp); return; } int i,j,k; for( i=0;i<n;i++){ k=tmp.size(); for( j=0;j<k;j++){ if(i==tmp[j]|| abs(k-j)==abs(i-tmp[j])) break; } if(j<k) continue; tmp.push_back(i); findSolution(n,pos,tmp); int end=tmp.size()-1; if(k!=end) tmp.erase(tmp.begin()+k, tmp.begin()+end); else tmp.erase(tmp.begin()+k); } } void drawSolution(int n,vector<vector<string> >&solve, vector<vector<int> >&pos){ for(int i=0;i<pos.size();i++){ string s(n,'.'); vector<string>row(n,s); for(int j=0;j<n;j++){ row[j][pos[i][j]]='Q'; } solve.push_back(row); } } vector<vector<string> > solveNQueens(int n) { vector<vector<string> >solve; if(n<1) return solve; vector<vector<int> >pos; vector<int>tmp; findSolution(n,pos,tmp); if(pos.empty()) return solve; drawSolution(n,solve,pos); return solve; } };
class Solution {
public:
vector<vector<string>> solveNQueens(int n) {
vector<vector<string>> res;
vector<string> cur(n, string(n, '.')); // 初始化棋盘,所有的位置都没有摆放皇后
dfs(res, cur, n, 0);
return res;
}
void dfs(vector<vector<string>> &res, vector<string> &cur, int &n, int row) {
if (row == n) { // 当超出行数超出了棋盘,则把这次搜索的结果放入res中。
res.push_back(cur);
return;
}
for (int j = 0; j < n; j++) {
if (isValid(cur, n, row, j)) { // 判断在(row, j)处是否可以放一个皇后
cur[row][j] = 'Q'; // 如果可以,则放一个皇后
dfs(res, cur, n, row + 1); // 继续在下一行找一个位置放皇后
cur[row][j] = '.'; // 因为需要找到所有可能的情况,所以必然需要对每一行进行回退。去判断这一行的下一列是否可以放皇后。
}
}
}
bool isValid(vector<string> &cur, int &n, int row, int col) {
// 检查列
for (int i = 0; i < row; i++) {
if (cur[i][col] == 'Q') {
return false;
}
}
// 检查反斜线
for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
if (cur[i][j] == 'Q') {
return false;
}
}
// 检查斜线
for (int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {
if (cur[i][j] == 'Q') {
return false;
}
}
return true;
}
};