Leetcode51:N皇后
题目:N皇后问题是把N个皇后放在一个N×N棋盘上,使皇后之间不会互相攻击(任意两个皇后都不能处于同一行、同一列或同一斜线上)。给出一个整数n,返回n皇后问题的所有摆放方案。
分析:对于N皇后问题,首先注意到两个细节,第一,一行只可能有一个皇后且一列也只可能有一个皇后;第二,对于所有的主对角线有行号 + 列号 = 常数,对于所有的次对角线(x = y)有行号 - 列号 = 常数。因为每行每列主副对角线不能有多个皇后,所以我们可以先考虑皇后放在第一行中的每个位置,定义列,主副对角线数组来记录该位置的三个方向是否已经存在皇后,如果不存在,就进行放置,并且对这个位置的三个方向进行标记,递归求解下一行的皇后位置,然后再进行回溯求解其它的解。
//定义列、主对角线、副对角线
private boolean[] col;
private boolean[] dia1;
private boolean[] dia2;
private List<List<String>> result = new ArrayList<>();
public List<List<String>> solveNQueens(int n) {
List<String> list = new ArrayList<>();
col = new boolean[n];
dia1= new boolean[2*n-1];
dia2 = new boolean[2*n-1];
putQueen(n,list,0);
return result;
}
private void putQueen(int n, List<String> list, int row) {
if(row == n){
result.add(new ArrayList<>(list));
return;
}
char[] ch = new char[n];
Arrays.fill(ch, '.');
// 遍历当前 row 行的所有位置
for(int i = 0;i < n;i++){
if(!col[i] && !dia1[row-i+n-1] && !dia2[row+i]){
//试探
ch[i] = 'Q';list.add(String.valueOf(ch));
col[i] = true;dia1[row-i+n-1] = true;dia2[row+i] = true;
putQueen(n,list,row + 1);//试着寻找下一行
//回溯
list.remove(list.size() - 1);ch[i] = '.';
col[i] = false;dia1[row-i+n-1] = false;dia2[row+i] = false;
}
}
}
Leetcode52:N皇后II
题目:继续思考“n-queens”问题。这次我们不是输出皇后的排列情况,而是输出n皇后问题一共有多少种解法
分析:思路跟上题一样,只是我们不需要记录每次结果皇后的排列情况,而只是添加计数器来求解解法个数。
//定义列、主对角线、副对角线
private boolean[] col;
private boolean[] dia1;
private boolean[] dia2;
private int count;
public int totalNQueens(int n) {
col = new boolean[n];
dia1= new boolean[2*n-1];
dia2 = new boolean[2*n-1];
putQueen(n,0);
return count;
}
private void putQueen(int n,int row) {
if(row == n){
count++;
return;
}
// 遍历当前 row 行的所有位置
for(int i = 0;i < n;i++){
if(!col[i] && !dia1[row-i+n-1] && !dia2[row+i]){
//试探
col[i] = true;dia1[row-i+n-1] = true;dia2[row+i] = true;
putQueen(n,row + 1);//试着寻找下一行
//回溯
col[i] = false;dia1[row-i+n-1] = false;dia2[row+i] = false;
}
}
}