题目地址:
https://leetcode.com/problems/n-queens/
经典的N皇后问题。DFS回溯+剪枝。代码如下:
import java.util.ArrayList;
import java.util.List;
public class Solution {
public List<List<String>> solveNQueens(int n) {
List<List<String>> res = new ArrayList<>();
if (n == 0) {
return res;
}
int[] pos = new int[n];
dfs(pos, 0, res);
return res;
}
// 表示当前正在摆放第k行
private void dfs(int[] pos, int k, List<List<String>> res) {
// 如果k == pos.length,说明前k行已经顺利摆放好,且无矛盾,这时可以加进最后的结果中了
if (k == pos.length) {
res.add(buildBoard(pos));
return;
}
for (int i = 0; i < pos.length; i++) {
// 尝试摆放第k行的第i个位置。如果能摆放,就摆下一行
if (check(pos, k, i)) {
pos[k] = i;
helper(pos, k + 1, res);
}
}
}
// 正在摆第k行的第i个位置,check一下这个位置是否能摆
private boolean check(int[] pos, int k, int i) {
for (int dif = 1; dif <= k; dif++) {
// check左斜上方
if (i - dif >= 0 && pos[k - dif] == i - dif) {
return false;
}
// check右斜上方
if (i + dif <= pos.length && pos[k - dif] == i + dif) {
return false;
}
// check正上方
if (pos[k - dif] == i) {
return false;
}
}
return true;
}
// 根据每行的皇后位置来build出棋盘
private List<String> buildBoard(int[] pos) {
List<String> list = new ArrayList<>();
StringBuilder sb = new StringBuilder(pos.length);
for (int i = 0; i < pos.length; i++) {
for (int j = 0; j < pos.length; j++) {
if (j != pos[i]) {
sb.append('.');
} else {
sb.append('Q');
}
}
list.add(sb.toString());
sb.setLength(0);
}
return list;
}
}
时间复杂度 ,类似于先生成全排列,再把答案加到res里去(需要 ,因为棋盘有两维)。空间复杂度 。
因为有剪枝,所以时间复杂度不太容易估计出来。这里取的是上界,实际要比它小一些。