LeetCode51-N皇后
题目
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。
输入: 4
输出: [
[".Q…", // 解法 1
“…Q”,
“Q…”,
“…Q.”],
["…Q.", // 解法 2
“Q…”,
“…Q”,
“.Q…”]
]
解释: 4 皇后问题存在两个不同的解法。
提示:
皇后,是国际象棋中的棋子,意味着国王的妻子。皇后只做一件事,那就是“吃子”。当她遇见可以吃的棋子时,就迅速冲上去吃掉棋子。当然,她横、竖、斜都可走一到棋盘边,可进可退。
解法
使用回溯,这个题目可以按行来解:
一开始定一个visited数组,表示是否可以访问,第i行定准之后,将下面的visited数组修改,同一行(第i 行)的和上面(0…i-1行)的数组都不用修改,不要忘记,左斜下也要改。
注意:
(1)每次使用新的temp数组代替visited数组向下递归的时候,要执行深拷贝
(2)每次向cur加入新的String之后,再递归结束后,不要忘记删除它
class Solution {
private StringBuilder stb = new StringBuilder();
public List<List<String>> solveNQueens(int n) {
int[][] visited = new int[n][n];
List<List<String>> res = new LinkedList<>();
for(int i = 0 ; i < n ; ++i){
stb.append('.');
}
for(int i = 0 ; i < n ; ++i){
//执行深拷贝
int[][] temp = new int[n][n];
for(int j = 0 ; j < n ; ++j){
System.arraycopy(visited[j],0,temp[j],0,n);
}
change(temp,0,i,n);
String s = myString(i);
Deque<String> cur = new LinkedList<>();
cur.add(s);
dfs(n,res,temp,0,cur);
}
return res;
}
//回溯方法
public void dfs(int n, List<List<String>> res, int[][] visited, int h,Deque<String> cur){
if(h == n-1){
res.add(new LinkedList<>(cur));
return;
}
++h;//下一行
for(int i = 0 ; i < n ; ++i){
if(visited[h][i]==0){
int[][] temp = new int[n][n];
for(int j = 0 ; j < n ; ++j){
System.arraycopy(visited[j],0,temp[j],0,n);
}
change(temp,h,i,n);
String s = myString(i);
cur.add(s);
dfs(n,res,temp,h,cur);
cur.removeLast();
}
}
return;
}
//确定某个位置后,修改visited
public void change(int[][] visited,int i , int j , int n){
int index = 0;
for(int h = i ; h < n ; ++h){
visited[h][j] = 1;
if(j+index<n){
visited[h][j+index] = 1;
}
if(j-index>=0){
visited[h][j-index] = 1;
}
++index;
}
}
//得到某行的String
public String myString(int i){
stb.setCharAt(i,'Q');
String res = stb.toString();
stb.setCharAt(i,'.');
return res;
}
}