概述
1.回溯算法效率
2.回溯解决的问题
- 组合问题:N个数里面按某规则找出k个数的集合
- 切割问题:字符串按某规则有几种切割方式
- 子集问题:N个数的集合里有多少符合条件的子集
- 排列问题:N个数按某规则全排列,有几种排列方式
- 棋盘问题:N皇后,解数独等等
3.回溯模板
- 所有回溯问题可抽象成树
- 回溯法一般是在集合中递归搜索
- 集合大小构成树宽度,递归深度构成树深度
![在这里插入图片描述](https://img-blog.csdnimg.cn/7e6e3e47ad84456796c3ca611ca9ba71.png)
- 模板
public void backtracking(参数){
if(终止条件){
存放结果;
return;
}
for(本层集合中元素(树中孩子节点数量是集合大小)){
处理节点;
backtracking(路径,选择列表);
回溯,撤销处理结果
}
}
- 回溯所有情况
![在这里插入图片描述](https://img-blog.csdnimg.cn/6403627ede784dd6abe44a386521ddb5.png)
class Solution {
List<List<Integer>> ress = new ArrayList<List<Integer>>();
LinkedList<Integer> res = new LinkedList<Integer>();
public List<List<Integer>> combine(int n, int k) {
backtracking(n,k,1);
return ress;
}
public void backtracking(int n,int k,int startIndex){
if(res.size()==k){
ress.add(new ArrayList(res));
return ;
}
for(int i=startIndex;i<=n;i++){
res.add(i);
backtracking(n,k,i+1);
res.removeLast();
}
}
}
- 回溯修剪分枝
![在这里插入图片描述](https://img-blog.csdnimg.cn/fda6596d2f44478ea8b76ba1f9df1746.png)
class Solution {
List<List<Integer>> ress = new ArrayList<List<Integer>>();
LinkedList<Integer> res = new LinkedList<Integer>();
public List<List<Integer>> combine(int n, int k) {
backtracking(n,k,1);
return ress;
}
public void backtracking(int n,int k,int startIndex){
if(res.size()==k){
ress.add(new ArrayList(res));
return ;
}
for(int i=startIndex;i<=n-(k-res.size())+1;i++){
res.add(i);
backtracking(n,k,i+1);
res.removeLast();
}
}
}
class Solution {
List<List<Integer>> ress = new ArrayList<List<Integer>>();
LinkedList<Integer> res = new LinkedList<Integer>();
public List<List<Integer>> combinationSum3(int k, int n) {
backtracking(k,n,1);
return ress;
}
public void backtracking(int k,int n,int startIndex){
if(res.size()==k && n==0){
ress.add(new ArrayList(res));
return ;
}
for(int i=startIndex;i<=9;i++){
res.add(i);
backtracking(k,n-i,i+1);
res.removeLast();
}
}
}
class Solution {
List<List<Integer>> ress = new ArrayList<List<Integer>>();
LinkedList<Integer> res = new LinkedList<Integer>();
public List<List<Integer>> combinationSum3(int k, int n) {
backtracking(k,n,1);
return ress;
}
public void backtracking(int k,int n,int startIndex){
if(res.size()==k && n==0){
ress.add(new ArrayList(res));
return ;
}
if(res.size()>k || n<0) return;
for(int i=startIndex;i<=9-(k-res.size())+1;i++){
res.add(i);
backtracking(k,n-i,i+1);
res.removeLast();
}
}
}
class Solution {
List<String> res = new ArrayList<String>();
StringBuilder temp = new StringBuilder();
public List<String> letterCombinations(String digits) {
if(digits==null||digits.length()==0) return res;
String[] nums={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
backtracking(digits,nums,0);
return res;
}
public void backtracking(String digits,String[] nums,int num){
if(num==digits.length()){
res.add(temp.toString());
return ;
}
String str = nums[digits.charAt(num)-'0'];
for(int i=0;i<str.length();i++){
temp.append(str.charAt(i));
backtracking(digits,nums,num+1);
temp.deleteCharAt(temp.length()-1);
}
}
}
class Solution {
List<List<Integer>> ress = new ArrayList<List<Integer>>();
LinkedList<Integer> res = new LinkedList<Integer>();
int sum = 0;
public List<List<Integer>> combinationSum(int[] candidates, int target) {
backtracking(candidates,target,0);
return ress;
}
public void backtracking(int[] candidates,int target,int startIndex){
if(sum >= target){
if(sum == target){
ress.add(new ArrayList(res));
}
return;
}
for(int i=startIndex;i<candidates.length;i++){
sum += candidates[i];
res.add(candidates[i]);
backtracking(candidates,target,i);
res.removeLast();
sum -= candidates[i];
}
}
}
class Solution {
List<List<Integer>> ress = new ArrayList<List<Integer>>();
LinkedList<Integer> res = new LinkedList<Integer>();
int sum = 0;
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
backtracking(candidates,target,0);
return ress;
}
public void backtracking(int[] candidates,int target,int startIndex){
if(sum == target){
ress.add(new ArrayList(res));
return;
}
for(int i=startIndex;i<candidates.length;i++){
if(sum+candidates[i]>target) break;
sum += candidates[i];
res.add(candidates[i]);
backtracking(candidates,target,i);
res.removeLast();
sum -= candidates[i];
}
}
}
class Solution {
List<List<Integer>> ress = new ArrayList<List<Integer>>();
LinkedList<Integer> res = new LinkedList<Integer>();
int sum = 0;
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
backtracking(candidates,target,0);
return ress;
}
public void backtracking(int[] candidates,int target,int startIndex){
if(sum >= target){
if(sum == target){
ress.add(new ArrayList(res));
}
return;
}
for(int i=startIndex;i<candidates.length;i++){
if(i>startIndex && candidates[i]==candidates[i-1]) continue;
sum += candidates[i];
res.add(candidates[i]);
backtracking(candidates,target,i+1);
res.removeLast();
sum -= candidates[i];
}
}
}
class Solution {
List<List<Integer>> ress = new ArrayList<List<Integer>>();
LinkedList<Integer> res = new LinkedList<Integer>();
int sum = 0;
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
backtracking(candidates,target,0);
return ress;
}
public void backtracking(int[] candidates,int target,int startIndex){
if(sum == target){
ress.add(new ArrayList(res));
return;
}
for(int i=startIndex;i<candidates.length;i++){
if(sum+candidates[i]>target) break;
if(i>startIndex && candidates[i]==candidates[i-1]) continue;
sum += candidates[i];
res.add(candidates[i]);
backtracking(candidates,target,i+1);
res.removeLast();
sum -= candidates[i];
}
}
}