-
如题:
思路:
-
该题是经典回溯法题目
-
我们从第一行开始逐行放置皇后,然后放置第二行的皇后,第二行皇后放置的时候需要和第一行皇后比较位置,如果是同一列或者在同一斜线上就不能放置
-
我们可以使用一个select数组记录每一行皇后放在第几列,数组的下标表示第几行,值表示第几列,例如select[3]=1,表示第三行的皇后放置在第一列
-
检验是否同一列:
- 例如我们检验第4行皇后能否放在第4列,只需要遍历select数组0-3的值,看是否有select[i]=4,
-
检验是否同一斜线:
- 例如我们检验第4行皇后能否放在第4列,只需要遍历select数组0-3的值,检查每一行皇后所在列数和当前列数差值的绝对值是否等于每一行皇后的行数和当前行数差值的绝对值是否相等,如果相等则它们处于同一斜线
-
代码:
class Solution {
//用来返回最后所有放置的结果
List<List<String>> res = new ArrayList<>();
//用来统计单次放置的结果,统计完后加入到res
List<String> add;
//长度为n,select[0]=1表示第0行的皇后放在1的位置
int[] select;
//用来配合select形成每行的结果,加入到add中
char[] temp;
public List<List<String>> solveNQueens(int n) {
add = new ArrayList<>(n);
select = new int[n];
temp = new char[n];
backTrack(n,0,0);
return res;
}
//回溯法,从第row行开始,每行遍历0-n位置组个选择
public void backTrack(int n,int row,int col){
//当row==n的时候说明将0-n-1位置的皇后放置好了,select数组记录了每一行皇后放置的位置
if (row==n){
//将上次的结果清理
add.clear();
for (int i = 0; i < n; i++) {
Arrays.fill(temp,'.');
temp[select[i]]='Q';
add.add(new String(temp));
}
res.add(new ArrayList<>(add));
return;
}
for (int i = 0; i < n; i++) {
if (!canSet(select,row,i))continue;
//回溯法一般做出选择之后需要撤销选择,但这里不需要撤销,
// 因为我们下次选择的时候会覆盖这次选择结果,撤不撤销无所谓
select[row] = i;
backTrack(n,row+1,i);
}
}
public boolean canSet(int[] n,int row,int col){
for (int i = 0; i < row; i++) {
if (n[i]==col||Math.abs(i-row)==Math.abs(n[i]-col)){
return false;
}
}
return true;
}
}