一、先祭模板(转自LeetCode46 cllh1999 题解)
回溯法搜索树有两类,子集树(从n个元素的集合S中找到需要的子集)和排列树(确定n个元素满足某种排列)
子集树模板为:
public void backTrack(int n) {
if (t > n) {
outPut(x)
} else {
for (int i = 0; i < n; i++) {
x[t] = i;
if (约束条件 && 边界条件) {
backTrack(t + 1);
}
}
}
}
排列树模板为:
public void backTrack(int n) {
if (t > n) {
outPut(x)
} else {
for (int i = t; i < n; i++) {
swap(x[t], x[i]);
if (约束条件 && 边界条件) {
backTrack(t + 1);
}
swap(x[t], x[i]);
}
}
}
二、再上例子
(1)排列树
给定一个可包含重复数字的序列,返回所有不重复的全排列。
示例:
输入: [1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
代码:
class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> re = new ArrayList<>();
Arrays.sort(nums);
boolean[] flags = new boolean[nums.length];
DFS(re, flags, nums, 0);
return re;
}
private static boolean isRepeat(int[] nums, int first, int n){
int temp = nums[n];
for (int i=first; i<n; i++){
if (nums[i] == temp){
return true;
}
}
return false;
}
public static void swapHelper(int[] nums, int start, int end) {
int temp = nums[start];
nums[start] = nums[end];
nums[end] = temp;
}
public static void DFS(List<List<Integer>> re, boolean[] flags, int[] nums, int index) {
if (index == nums.length) {
List<Integer> temp = new ArrayList<>();
for (int j = 0; j < nums.length; j++) {
temp.add(nums[j]);
}
re.add(temp);
return;
}
for (int i = index; i < nums.length; i++) {
if(!isRepeat(nums, index, i)) {
swapHelper(nums, index, i);
DFS(re, flags, nums, index + 1);
swapHelper(nums, index, i);
}
}
}
}
(2)子集树
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
下图为 8 皇后问题的一种解法。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
示例:
输入: 4
输出: [
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。
代码:
class Solution {
private List<List<String>> outPut = new ArrayList<>();
private int[] queens;
public List<List<String>> solveNQueens(int n) {
queens = new int[n];
for (int i = 0; i < queens.length; i++) {
queens[i] = 0;
}
backTrack(0, n);
return outPut;
}
private void backTrack(int t, int n) {
if (t >= n) {
standardPrint(queens);
} else {
for (int i = 0; i < n; i++) {
queens[t] = i;
//使用约束条件剪去不必要分枝
if (judge(t)) {
backTrack(t + 1, n);
}
}
}
}
//约束条件
private boolean judge(int k) {
for (int i = 0; i < k; i++) {
if (Math.abs(k - i) == Math.abs(queens[k] - queens[i]) || queens[k] == queens[i]) {
return false;
}
}
return true;
}
private void standardPrint(int[] res){
List<String> stringList = new ArrayList<>();
for (int re : res) {
StringBuilder sb = new StringBuilder();
for (int j = 0; j < res.length; j++) {
if (j == re) {
sb.append("Q");
} else {
sb.append(".");
}
}
stringList.add(sb.toString());
}
outPut.add(stringList);
}
}