leetcode第51题n皇后
思路:
-
n皇后是很经典的回溯问题,难就难在怎样进行设计,方法的划分也体挺关键的。
-
根据n创建一个chessboard 初始化全为’.’;
-
回溯的参数,分别是 n chessboard row 当n == row的时候,row - 1 行中的皇后已经填充完毕,说明我们找到了一种合理的情况,可以添加到结果集中。
-
回溯的过程就是从第一行开始放第一个皇后的,放在第一行的第一个位置,回溯,往第二行的第一个位置放,发现当前的位置无效,i++ 放在第二行的第二个位置,还是无效,放在第而行的第三个位置,就这样一点一点的枚举,发现有一行实在是填不进去皇后了,返回到上一行,移开当前行中填充的皇后,重新往这行放皇后(对应的是col++),当我们把每一行都填充满的时候,发现chessboard满足放置皇后的规则。
-
如果写验证位置是不是可以放皇后?
- 当前位置这一行中是不是已经有了皇后了
- 当前位置左上角四十五度是不是有皇后了 row- 1;col + 1
- 当前位置右上角一百三十五度是不是有皇后了 row - 1;col + 1
为什么不验证当前行是不是有还有别的皇后?
- 每一行只放了一个皇后,就算是这个已经放置了,但是我发现在以后这种可以验证出来不合理,我就要把这个位置的皇后去掉,col++,在后一个位置放皇后。
- 老生常谈,皇后是一行一行的放了,想要在当前行中放皇后,就说明当前行和之后的行中,是没有皇后的。只需要检验我要防止的这个位置他的左上角和右上角是不是有皇后,有皇后,就说明我们不能这样放置。
class Solution {
List<List<String>> res;
public List<List<String>> solveNQueens(int n) {
//慢慢一点点写代码吧 还是不是很容易\
//为什么可以这么多的啊,我裂开了
char[][] chessboard = new char[n][n];
res = new LinkedList<>();
for(char[] temp : chessboard){
Arrays.fill(temp,'.');
}
backTrack(n,chessboard,0);
return res;
}
void backTrack(int n,char[][] chessboard,int row){
if(row == n){
res.add(toList(chessboard));
return;
}
for(int col = 0;col < n;col++){
if(isValid(col,row,n,chessboard)){
chessboard[row][col] = 'Q';
backTrack(n,chessboard,row + 1);
chessboard[row][col] = '.';
}
}
}
public List<String> toList(char[][] chessboard){
List<String> helper = new LinkedList<>();
for(char[] temp : chessboard){
helper.add(String.copyValueOf(temp));
}
return helper;
}
public boolean isValid(int col,int row,int n,char[][] chessboard){
//检查列
for(int i = 0;i < row;i++){
if(chessboard[i][col] == 'Q'){
return false;
}
}
//检查45度角上是不是有皇后
for(int i = row - 1,j = col - 1;i >= 0 && j >= 0;i--,j--){
if(chessboard[i][j] == 'Q'){
return false;
}
}
//检查135度角
for(int i = row - 1,j = col + 1;i >= 0 && j < n;i--,j++){
if(chessboard[i][j] == 'Q'){
return false;
}
}
return true;
}
}