回溯算法框架如下
初始化结果集
主函数:接收传入参数、初始化(路径,选择列表)、执行回溯函数backtrack、返回结果集
回溯函数backtrack:判断结束条件(达到了就加入结果集并返回)、依次判断选择列表中的结果是否符合题中条件(不符合的跳过)、将第一个符合的结果加入路径并更改对应的标识、使用新的结果递归回溯函数、将结果从路径中拿掉并去掉对应的标识
for 选择 in 选择列表:
# 做选择
将该选择从选择列表移除
路径.add(选择)
backtrack(路径, 选择列表)
# 撤销选择
路径.remove(选择)
将该选择再加⼊选择列表
Leetcode 41 全排列(力扣)
class Solution {
LinkedList<List<Integer>> res = new LinkedList<>();
public List<List<Integer>> permute(int[] nums) {
/**
回溯算法暴力破解
新建一个结果数组
主函数:声明track、used数组、以及递归函数
一个track代表一个路径
*/
LinkedList<Integer> track = new LinkedList<>();
boolean[] used = new boolean[nums.length];
backtrack(nums,track,used);
return res;
}
void backtrack(int[] nums,LinkedList<Integer> track, boolean[] used){
//结束条件
if(track.size() == nums.length){
res.add(new LinkedList(track));
return;
}
for(int i = 0; i<nums.length; i++){
if(used[i] == true){
//该节点已加入track 剪枝
continue;
}
//递归前做的事:加入节点,更改used
track.add(nums[i]);
used[i] = true;
//递归
backtrack(nums,track,used);
//递归后做的事:删除节点,更改used
track.removeLast();
used[i] = false;
}
}
}
Leetcode 51 N皇后(力扣)
class Solution {
List<List<String>> result = new LinkedList<>();//存放所有结果
public List<List<String>> solveNQueens(int n) {
//新建一个棋盘
List<String> board = new LinkedList<>();
StringBuilder stringBuilder = new StringBuilder();
//初始化棋盘 全部置空
stringBuilder.append(".".repeat(n));
for (int i = 0; i < n; i++) {
board.add(stringBuilder.toString());
}
backTrack(0,board);
return result;
}
//路径:board中小于row的那些行都已经成功放置了皇后
//选择列表:第row行的所有列都是放置皇后的选择
//结束条件:row 超过 board 的最后一行
void backTrack(int row,List<String> board){
//回溯终止条件
if (row == board.size()){//终止条件 递归到了最后一个行 直接跳出
result.add(new LinkedList<>(board));//将目前的结果中的添加到result中
return;
}
int n = board.get(row).length();//获取当前游标所在的行的 String长度
//开始穷举 从 当前行的 第0 列开始 处理节点
for (int col = 0; col < n ; col++) {
//处理节点 (检查节点合法性 , 如果合法 )
if (!isValid(row,col,board)){//检查 当前行 的 所有列的节点是否合法
continue;//如果不合法直接跳过
}
String str = board.get(row).substring(0,col) + 'Q' + board.get(row).substring(col+1);
board.set(row,str);//将上述的替换后的String 代替到 游标所在的row
//递归 深入子树
backTrack(row+1,board);//对深入的下一行进行递归操作
//回溯 ,撤销处理结果
str = board.get(row).substring(0,col) + '.' + board.get(row).substring(col+1);
board.set(row,str);
}
}
boolean isValid(int row,int column,List<String> board){
int n = board.size();
//判断列位置是否合法
for (int i = 0; i < n; i++) {
if (board.get(i).charAt(column) == 'Q'){//第 i行 第 column 列 的字符
return false;
}
}
//判断是否与右上方发生冲突
for (int i = row -1,j = column + 1; i >= 0 && j < n; i--,j++ ) {
if (board.get(i).charAt(j) == 'Q'){
return false;
}
}
//判断 是否与 左上方冲突
for (int i = row -1,j = column -1 ; i >=0 && j>=0 ; i--,j--) {
if (board.get(i).charAt(j) == 'Q'){
return false;
}
}
return true;
}
}