算法从入门到放弃——第四期 岛屿_u014783007的博客-CSDN博客
之前有写了一篇岛屿的问题,今天来看一个岛屿的变种,N皇后
题目如下
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
示例 1:
输入:n = 4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
解释:如上图所示,4 皇后问题存在两个不同的解法。
这题在leetcode是困难,但是做过岛屿之后,明眼一看感受是能做, 虽然返回奇奇怪怪,但是本质还是岛屿问题,岛屿问题模板就是bfs岛屿块,脑海里两层循环有了,之后就是放“Q”,放第一个肯定放哪都行,放第二个就要验证能不能放了,而验证的方法需要考虑一下,这里如果我们是从左往右,从上到下放,那么我需要检测我的上方,左方,左上,右上四个角度是不是已经放过“Q”了即可,如果不满足条件就回溯。
好像结束了,没错,过程就是这么简单,然后只要代码实现就可以了
public static void setChess(String[][] chess, int row, List<List<String>> result) {
if (row == chess.length) {
List<String> ss = new ArrayList<>();
for (int i = 0; i < chess.length; i++) {
String s = "";
for (int j = 0; j < chess[0].length; j++) {
s+=chess[i][j];
}
ss.add(s);
}
result.add(new ArrayList<>(ss));
ss.clear();
return;
}
for (int col = 0; col < chess[0].length; col++) {
if (positionIsValid(chess, row, col)) {
chess[row][col] = "Q";
setChess(chess, row + 1, result);
chess[row][col] = ".";
}
}
}
public static boolean positionIsValid(String[][] chess, int row, int col) {
//注意外层是从上到下,从左到右遍历的
//那么对于当前节点而言,有可能填过Q区域,只能在上,左,右上,左上四个方向上
for (int i = 0; i < row; i++) {
if (chess[i][col].equals("Q")) {
return false;
}
}
for (int i = 0; i < col; i++) {
if (chess[row][i].equals("Q")) {
return false;
}
}
for (int i = row - 1, j = col + 1; i >= 0 && j < chess[0].length; i--, j++) {
if (chess[i][j].equals("Q")) {
return false;
}
}
for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
if (chess[i][j].equals("Q")) {
return false;
}
}
return true;
}
这种题目一般不会作为面试出现,总体而言为了考察递归和回溯,但是需要很多额外的方法去体现算法,这不太符合面试的要求,当然熟练掌握回溯做这道题应该也不会有难度