LeetCode-51. N-Queens(Hard):
The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.
Given an integer n, return all distinct solutions to the n-queens puzzle.
Each solution contains a distinct board configuration of the n-queens' placement, where 'Q'
and '.'
both indicate a queen and an empty space respectively.
Example:
Input: 4
Output: [
[".Q..", // Solution 1
"...Q",
"Q...",
"..Q."],
["..Q.", // Solution 2
"Q...",
"...Q",
".Q.."]
]
Explanation: There exist two distinct solutions to the 4-queens puzzle as shown above.
大神解法:
这道题是经典的八皇后问题,要用回溯算法做,我尝试解了一下发现有点复杂,不知道有没有什么套路于是直接找了网上的答案,这段答案速度和空间都是最优的,于是拿来详细分析一下。
首先查了一下回溯和动态规划、递归的异同,发现他们其实特别相似,是近亲,不同点是回溯的子结构不一定是最优的,是一种以尝试为思想的解法,这就需要算法能处理万一子结构走不通还要回来的状态恢复问题。
看一下答案最下面的for循环,发现递归求解子问题之后立刻就恢复了之前修改过的状态,这可能就是回溯算法的精髓吧。
至于程序开头定义的三个boolean数组没太理解为什么,只知道是为了标记各个位置的横竖斜方向有没有王后的,可能他这种方法效率比较高吧。。。
class Solution {
public List<List<String>> solveNQueens(int n) {
boolean[] col = new boolean[n];
boolean[] diagnolCol = new boolean[2*n-1];
boolean[] diagnolRol = new boolean[2*n-1];
char[][] game = new char[n][n];
for(int i = 0; i < game.length; i++) {
Arrays.fill(game[i], '.');
}
List<List<String>> res = new ArrayList<>();
solveNQueens(col, diagnolCol, diagnolRol, game, 0, n, res);
return res;
}
private void solveNQueens(boolean[] col, boolean[] diagnolCol, boolean[] diagnolRol, char[][] game, int row, int n, List<List<String>> res) {
if(row == n) {
List<String> sol = new ArrayList<>();
for(char[] line : game) {
sol.add(new String(line));
}
res.add(sol);
return;
}
for(int i = 0; i < n; i++) {
//!col !diagnolCol[i+j] !diagnolRol[n-1 + row-i]
if(col[i] || diagnolCol[i+row] || diagnolRol[n-1 + row-i]) {
continue;
}
game[row][i] = 'Q';
col[i] = true;
diagnolCol[i+row] = true;
diagnolRol[n-1 + row-i] = true;
solveNQueens(col, diagnolCol, diagnolRol, game, row+1, n, res);
col[i] = false;
diagnolCol[i+row] = false;
diagnolRol[n-1 + row-i] = false;
game[row][i] = '.';
}
}
}