回溯算法
- 实际上就是一个决策树的遍历过程
- 路径:已经做出的选择
- 选择列表:是你当前可以做的选择
- 结束条件:到达决策树底层,无法再做选择的条件
- 经典问题:【全排列】【N皇后问题】
1. 全排列问题
https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL3N6X21tYml6X2pwZy9naWJrSXowTVZxZEYxdW1BZHlYdVBxNTRpYnc3WDIzbW5hR0ppYW1idHBxYzR2a2hzcVpZb0VaV2lhbmlic0ltdER2bVhSTUNKdVVCOGdrTGZDSlZBUUR0MlJBLzY0MD93eF9mbXQ9anBlZw?x-oss-process=image/format,png
// 全排列问题
public class Backtrack {
List<List<Integer>> res = new LinkedList<>();
List<List<Integer>> permute(int[] nums) {
LinkedList<Integer> list = new LinkedList<>();
backtrack(nums, list);
return res;
}
void backtrack(int[] nums, LinkedList<Integer> list) {
if (nums.length == list.size()) {
res.add(list);
return;
}
for (int i = 0; i < nums.length - 1; i++) {
if (list.contains(nums[i])) {
continue;
}
// 做决策
list.add(nums[i]);
// 进入下一层决策树
backtrack(nums, list);
// 取消决策
list.removeLast();
}
}
}
2. N皇后问题
-
给你一个NxN的期盼,让你放置N个皇后,使得他们不能互相攻击
-
皇后可以攻击同一行,同一列,左上左下,右上右下 四个方向的任意单位
-
解法也就是上述全排列方案的适当调整
- 添加了isValid()的函数校验是否有皇后冲突
- 初始化了一个字符串链表棋盘
public class Backtrack {
List<List<String>> queueMatrix = new LinkedList<>();
List<String> board = new LinkedList<>();
int n = 0;
List<List<String>> solveNQueens(int n) {
this.n = n;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) sb.append('.');
for (int i = 0; i < n; i++) board.add(sb.toString());
queenBacktrack( 0);
return queueMatrix;
}
void queenBacktrack(int row) {
if (row == n) {
// 结束了一次决策树(全排列)
queueMatrix.add(new LinkedList<>(board));
return;
}
for (int col = 0; col < n; col++) {
if (!isValid(row, col)) {
continue;
}
// 合法,做决策
StringBuilder sb = new StringBuilder(board.get(row));
sb.setCharAt(col, 'Q');
board.set(row, sb.toString());
// 递归
queenBacktrack(row + 1);
// 回退
StringBuilder sb2 = new StringBuilder(board.get(row));
sb2.setCharAt(col, '.');
board.set(row, sb2.toString());
}
}
boolean isValid(int row, int col) {
for (int i = 0; i < row; i++) {
// 上面不能有Q
if (board.get(i).charAt(col) == 'Q') {
return false;
}
}
for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
// 左上方,不能有Q
if (board.get(i).charAt(j) == 'Q') {
return false;
}
}
for (int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {
// 右上方,不能有Q
if (board.get(i).charAt(j) == 'Q') {
return false;
}
}
return true;
}
}
网友评论