一个经典的回溯算法问题。回溯的本质是决策树的递归过程,用递归的方式遍历所有可能得结果,在遍历过程可以添加适当的判断来实现剪枝从而提高算法的性能。
对应本题,决策树的每一层元素可以对应为皇后在每一层所放置的位置,剪枝的判断条件为皇后的攻击范围(即不可将下一层的皇后放置在上层皇后的攻击范围内),由此套用回溯算法的模板即可得到答案。
class Solution {
//将数组转换为字符串
public List<String> charToString(char[][] chars){
List<String> result = new ArrayList<>();
for(char[] c : chars){
result.add(String.valueOf(c));
}
return result;
}
List<List<String>> res;
public List<List<String>> solveNQueens(int n) {
res = new ArrayList<>();
if(n<=0)return res;
char[][] board = new char[n][n];
for(char[] c : board){
Arrays.fill(c, '.');
}
backtrack(board, 0);
return res;
}
//回溯主函数
public void backtrack(char[][] board, int row){
if(row == board.length){
res.add(charToString(board));
return;
}
for(int i=0; i<board.length; i++){
if(!isValid(board, row, i))continue;
board[row][i] = 'Q';
backtrack(board, row+1);
board[row][i] = '.';
}
}
//剪枝函数,判断上层皇后的攻击范围
public boolean isValid(char[][] board, int row, int col){
int rows = board.length;
for(int i=0; i<row; i++){
if(board[i][col] == 'Q')return false;
}
for(int i=row-1, j=col-1; i>=0 && j>=0; i--,j--){
if(board[i][j] == 'Q')return false;
}
for(int i=row-1, j=col+1; i>=0 && j<rows; i--,j++){
if(board[i][j] == 'Q')return false;
}
return true;
}
}