Leetcode-51. N皇后
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
上图为 8 皇后问题的一种解法。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。
示例:
输入: 4
输出: [
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。
解法:看到这种题目,应该能想到使用dfs进行回溯,最浅层就是第一层,最深层就是第N层,每一层进行的操作就是查看有没有位置放置皇后,如果有,对下一层执行递归,没有就返回(这里可以执行剪枝避免无用路径);直到最后一层,如果有位置,添加到结果,没有往上回溯。时间复杂度O(N!),放置一个皇后方法不超过N种,放置两个皇后不超过N*(N-2)种,放置三个皇后不超过N*(N-2)(N-4)种,以此类推。空间复杂度O(N)
- Java
class Solution {
public List<List<String>> solveNQueens(int n) {
Set<Integer> left = new HashSet<>();
Set<Integer> right = new HashSet<>();
Set<Integer> cols = new HashSet<>();
List<Integer> tmp = new ArrayList<>();
List<List<Integer>> res = new ArrayList<>();
this.dfs(0, n, cols, left, right, tmp, res);
return this.formatting(res, n);
}
public void dfs(int level, int n, Set<Integer> cols, Set<Integer> left, Set<Integer> right, List<Integer> tmp, List<List<Integer>> res){
if (tmp.size()==n) {
// res.add(tmp); DO NOT ADD TMP DIRECTLY! tmp will change in backtracing! add a copy of tmp!
res.add(new ArrayList<>(tmp));
return;
}
for (int i=0;i<n;i++) {
if (!cols.contains(i) && !left.contains(level+i) && !right.contains(level-i)) {
cols.add(i);
left.add(level+i);
right.add(level-i);
tmp.add(i);
this.dfs(level+1, n, cols, left, right, tmp, res);
cols.remove(i);
left.remove(level+i);
right.remove(level-i);
tmp.remove(Integer.valueOf(i)); // remove(i) will not remove the i value in tmp ,but will remove the ith value! MARK THAT!
}
}
return ;
}
public List<List<String>> formatting(List<List<Integer>> lst, int n){
List<List<String>> res = new ArrayList<>();
for (List<Integer> tmp:lst) {
List<String> l = new ArrayList<>();
for (Integer col:tmp) {
String str = "";
for (int i=0;i<n;i++) {
if (i==col){
str += "Q";
}else{
str += ".";
}
}
l.add(str);
}
res.add(l);
}
return res;
}
}
- Python
class Solution:
def solveNQueens(self, n: int):
self.n, self.cols, self.left, self.right, self.tmp, self.res = n, set(), set(), set(), [], []
self.dfs(0)
return self.formatting()
def dfs(self, level):
if len(self.tmp) == self.n:
self.res.append(self.tmp.copy())
return
for i in range(self.n):
if i not in self.cols and (level+i) not in self.left and (level-i) not in self.right:
self.cols.add(i)
self.left.add(level+i)
self.right.add(level-i)
self.tmp.append(i)
self.dfs(level+1)
self.cols.remove(i)
self.left.remove(level+i)
self.right.remove(level-i)
self.tmp.pop()
return
def formatting(self):
l1 = []
for lst in self.res:
l = []
for num in lst:
str = ""
for i in range(self.n):
if i==num:
str += "Q"
else:
str += "."
l.append(str)
l1.append(l)
return l1
Leetcode-52. N皇后 II
给定一个整数 n,返回 n 皇后不同的解决方案的数量。
解法:同上题一样的方法。这道题和上一题都是用array来存储,不使用hashset的话,会减少很多时间,只给出java代码,因为解法实在是一毛一样
- Java
public class Solution {
int count = 0;
public int totalNQueens(int n) {
boolean[] cols = new boolean[n]; // columns |
boolean[] d1 = new boolean[2 * n]; // diagonals \
boolean[] d2 = new boolean[2 * n]; // diagonals /
backtracking(0, cols, d1, d2, n);
return count;
}
public void backtracking(int row, boolean[] cols, boolean[] d1, boolean []d2, int n) {
if(row == n) count++;
for(int col = 0; col < n; col++) {
int id1 = col - row + n;
int id2 = col + row;
if(cols[col] || d1[id1] || d2[id2]) continue;
cols[col] = true; d1[id1] = true; d2[id2] = true;
backtracking(row + 1, cols, d1, d2, n);
cols[col] = false; d1[id1] = false; d2[id2] = false;
}
}
}