欢迎访问我的个人博客zealyoung的个人博客
Leetcode51.N皇后问题
题目描述:
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。
示例:
输入: 4
输出: [
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。
思路:
N皇后问题是一道经典的回溯问题,回溯本质上也是一种搜索算法,在搜索过程中进行"剪枝" + “状态重置”,对于本题来说,例如我们将第二个皇后放在某一个位置不满足条件时,就不需要再去排列其他的皇后,而是直接回溯到放置第二个皇后的前一个状态,并尝试下一个位置,判断是回溯算法后就是如何剪枝让搜索更快,对于此题来说,每行一个皇后,根据不能相互攻击的条件,皇后不能出现在同一列,同一对角线(主、副),我们利用三个哈希表来存储三个条件。
代码:
class Solution {
public List<List<String>> solveNQueens(int n) {
List<List<String>> res = new ArrayList<>();
if(n == 0) return res;
int[] nums = new int[n];
for(int i = 0; i < n; i++){
nums[i] = i;
}
Set<Integer> col = new HashSet<>();
Set<Integer> master = new HashSet<>();
Set<Integer> slave = new HashSet<>();
Stack<Integer> s = new Stack<>();
backtrack(nums, 0, n, col, master, slave, s, res);
return res;
}
public void backtrack(int[] nums, int row, int n,
Set<Integer> col,
Set<Integer> master,
Set<Integer> slave,
Stack<Integer> s,
List<List<String>> res){
if(row == n){
res.add(makelist(s, n));
return;
}
for(int i = 0; i < n; i++){
if(!col.contains(i) && !master.contains(row - i) &&
!slave.contains(row + i)){
s.push(nums[i]);
col.add(i);
master.add(row - i);
slave.add(row + i);
backtrack(nums, row + 1, n, col, master, slave, s, res);
slave.remove(row + i);
master.remove(row - i);
col.remove(i);
s.pop();
}
}
}
public List<String> makelist(Stack<Integer> s, int n){
List<String> ans = new ArrayList<>();
for(Integer num : s){
StringBuffer str = new StringBuffer();
for(int i =0 ; i < n; i++){
str.append(".");
}
str.replace(num, num + 1, "Q");
ans.add(str.toString());
}
return ans;
}
}