回溯模板void backtracking(参数) { if (终止条件) { 存放结果; return; } for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) { 处理节点; backtracking(路径,选择列表); // 递归 回溯,撤销处理结果 } }
class Solution {
List<List<Integer>> res=new ArrayList<>();
LinkedList<Integer> path=new LinkedList<>();
public List<List<Integer>> combine(int n, int k) {
backTracking(n,k,1);
return res;
}
void backTracking(int n,int k,int start){
if(path.size()==k){
res.add(new ArrayList<>(path));
return;
}
for(int i=start;i<=n;i++){
path.add(i);
backTracking(n,k,i+1);
path.removeLast();
}
}
}
剪枝:就是剩下要选的数得有足够库存
k-path.size()<=n-i
由于是先执行判断再放入得+1:
k-path.size()<=n-i+1
// 上面剪枝 i <= n - (k - path.size()) + 1; 如果还是不清楚
// 也可以改为 if (path.size() > k) return; 执行效率上是一样的
笨办法
class Solution {
List<List<Integer>> res=new ArrayList<>();
LinkedList<Integer> path=new LinkedList<>();
public List<List<Integer>> combinationSum3(int k, int n) {
backTracking(n,k,1);
return res;
}
void backTracking(int n,int k,int start){
if(path.size()==k&&sum(path)==n){
res.add(new ArrayList<>(path));
return;
}
for(int i=start;i<=9;i++){
path.add(i);
backTracking(n,k,i+1);
path.removeLast();
}
}
int sum(List<Integer> path){
int m=0;
for(int p:path){
m+=p;
}
return m;
}
}
class Solution {
List<List<Integer>> result = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> combinationSum3(int k, int n) {
backTracking(n, k, 1, 0);
return result;
}
private void backTracking(int targetSum, int k, int startIndex, int sum) {
// 减枝
if (sum > targetSum) {
return;
}
if (path.size() == k && sum == targetSum) {
result.add(new ArrayList<>(path));
return;
}
// 减枝 9 - (k - path.size()) + 1
for (int i = startIndex; i <= 9 - (k - path.size()) + 1; i++) {
path.add(i);
sum += i;
backTracking(targetSum, k, i + 1, sum);
path.removeLast();
sum -= i;
}
}
}
class Solution {
List<List<Integer>> result = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
backTracking(candidates, 0, target, 0);
return result;
}
private void backTracking(int[] candidates, int startIndex, int targetSum,int sum) {
if (sum > targetSum) return;
if (sum == targetSum) {
result.add(new ArrayList<>(path));
return;
}
for (int i = startIndex; i <candidates.length ; i++) {
//去重
if(i>startIndex&&candidates[i]==candidates[i-1]) continue;
path.add(candidates[i]);
sum += candidates[i];
backTracking(candidates, i + 1,targetSum, sum);
path.removeLast();
sum -= candidates[i];
}
}
}
class Solution {
List<List<Integer>> result = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
backTracking(target, candidates, 0,0);
return result;
}
private void backTracking(int targetSum, int[] candidates, int sum,int startindex) {
if (sum > targetSum) return;
if (sum == targetSum) {
result.add(new ArrayList<>(path));
return;
}
for (int i =startindex ; i < candidates.length; i++) {
path.add(candidates[i]);
sum += candidates[i];
backTracking(targetSum, candidates, sum,i);
path.removeLast();
sum -= candidates[i];
}
}
}
class Solution {
List<String> list=new ArrayList<>();
StringBuilder temp=new StringBuilder();
String[] nums= {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
public List<String> letterCombinations(String digits) {
if(digits.length()==0) return list;
backTracking(digits,0);
return list;
}
void backTracking(String digits,int num){
if(temp.length()==digits.length()){
list.add(temp.toString());
return;
}
String numberString=nums[digits.charAt(num)-'0'];
for(int i=0;i<numberString.length();i++){
temp.append(numberString.charAt(i));
backTracking(digits,num+1);
temp.deleteCharAt(temp.length()-1);
}
}
}