回溯就是已经没什么别的办法了,回溯=暴力搜索,它相当于构建了一颗超大的树,然后每个叶子节点都是一种可能性,如果可能性符合条件,就要
回溯函数:
1.剪枝+如果到达最终状态,处理结果
2.元素进入与回退
比如说下面那个题,组合,给了一个k,k不确定,那就没法写for循环,只能回溯
回溯算法效率:就是拼谁剪枝剪得好,谁边界条件限制的好
第77题. 组合
给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。
思路:回溯
达到最终状态:那就是放元素的队列长度为k
剪枝:要达到不重复,需要在函数中有一个标识符,以及i不能选择太大,导致如果最后面剩余个数,每个都入队也不能达到k。这些都在for循环中限制了
注:我for循环中剪枝i<= n - (k - deque.size()) + 1 和不剪枝的速度差了22ms
class Solution {
List<List<Integer>> res = new LinkedList<>();
Deque<Integer> deque = new LinkedList<>();
public void backtracking(int n,int k,int startIndex){
if(deque.size()==k){
res.add(new LinkedList(deque));
return;
}
for(int i=startIndex;i<= n - (k - deque.size()) + 1;i++){
deque.offerLast(i);
backtracking(n,k,i+1);
deque.pollLast();
}
}
public List<List<Integer>> combine(int n, int k) {
backtracking(n,k,1);
return res;
}
}
第216题.组合总和III
回溯,就是要尽可能考虑全限制条件,剪枝条件,条件考虑的越全,算法性能越高
那么和上面的题相比,多了什么条件?
剪枝:如果deque长度达到n且和为k,加入结果集,如果和不为k,也要回退
如果长度未达到n且当前和超过k,剪枝
for循环中边界条件多了一个i<=9的限制
class Solution {
List<List<Integer>> res = new LinkedList<>();
Deque<Integer> deque = new LinkedList<>();
int count = 0;
public void backtracking(int n,int k,int startIndex){
if(deque.size()==k){
if(count==n) res.add(new LinkedList(deque));
return;
}
if(count>n-startIndex) return;
for(int i=startIndex;i<= Math.min(n - (k - deque.size()) + 1,9);i++){
deque.offerLast(i);
count+=i;
backtracking(n,k,i+1);
deque.pollLast();
count-=i;
}
}
public List<List<Integer>> combinationSum3(int k, int n) {
backtracking(n,k,1);
return res;
}
}
17.电话号码的字母组合
这个组合和最上面那个组合没有本质区别,只不过是组合怎么取值变了而已
class Solution {
List<String> res = new LinkedList<>();
Deque<Character> chars = new LinkedList<>();
public void backtracking(String digits,int index,Map<Character, String> phonemap){
if(digits.length()==0) return;
if(chars.size()==digits.length()){
StringBuilder str = new StringBuilder();
for(char c:chars){
str.append(c);
}
res.add(str.toString());
return;
}
String phonechar = phonemap.get(digits.charAt(index));
for(int i=0;i<phonechar.length();i++){
chars.offerLast(phonechar.charAt(i));
backtracking(digits,index+1,phonemap);
chars.pollLast();
}
}
public List<String> letterCombinations(String digits) {
Map<Character, String> phoneMap = new HashMap<Character, String>() {
{
put('2', "abc");
put('3', "def");
put('4', "ghi");
put('5', "jkl"</