【Leetcode】回溯法总结
回溯法的解体框架
解决一个回溯问题,实际上就是一个决策树的遍历过程。一般来说,我们需要解决三个问题:
路径:也就是已经做出的选择。
选择列表:也就是你当前可以做的选择。
结束条件:也就是到达决策树底层,无法再做选择的条件。
可以套用模板:
LinkedList result = new LinkedList();
public void backtrack(路径,选择列表){
if(满足结束条件){
result.add(结果);
}
for(选择:选择列表){
做出选择;
backtrack(路径,选择列表);
撤销选择;
}
}
面试题38. 字符串的排列

1 class Solution { 2 private Set<String> ans = new HashSet<>(); 3 public String[] permutation(String s) { 4 if(s == null || s.length() == 0){ 5 return new String[]{""}; 6 } 7 char[] chs = s.toCharArray(); 8 boolean[] visited = new boolean[chs.length]; 9 backtracing(s,chs,new StringBuilder(),visited); 10 String[] ansArr = new String[ans.size()]; 11 int i = 0; 12 for(String str: ans){ 13 ansArr[i++] = str; 14 } 15 return ansArr; 16 } 17 public void backtracing(String s,char[] chs, StringBuilder sb, boolean[] visited){ 18 if(sb.length() == s.length()){ 19 ans.add(sb.toString()); 20 } 21 for(int i = 0; i < chs.length; i++){ 22 if(visited[i]){ 23 continue; 24 } 25 visited[i] = true; 26 char c = chs[i]; 27 sb.append(c+""); 28 backtracing(s,chs,sb,visited); 29 sb.deleteCharAt(sb.length()-1); 30 visited[i] = false; 31 } 32 } 33 }
面试题34. 二叉树中和为某一值的路径
1 class Solution { 2 private List<List<Integer>> ans = new ArrayList<>(); 3 public List<List<Integer>> pathSum(TreeNode root, int sum) { 4 backtracing(root,sum,new ArrayList<>()); 5 return ans; 6 } 7 private void backtracing(TreeNode root, int sum, ArrayList<Integer> path){ 8 if(root == null) return; 9 sum -= root.val; 10 path.add(root.val); 11 if(sum == 0 && root.left == null && root.right == null){ 12 ans.add(new ArrayList<>(path)); 13 }else{ 14 backtracing(root.left,sum,path); 15 backtracing(root.right,sum,path); 16 } 17 path.remove(path.size()-1); 18 } 19 }
大数打印1~最大的n位数
在本题中,结束条件就是路径长于n,选择列表是0~9,当位于第一位的时候需要剪枝。
1 public class Solution { 2 private static List<String> list = new ArrayList<>(); 3 public static List<String> printNumbers(int n) { 4 trace(new StringBuilder(),n); 5 list.remove(0); 6 return list; 7 } 8 public static void trace(StringBuilder num, int n){ 9 if(num.length() > n){ 10 return; 11 } 12 list.add(num.toString()); 13 for(int i = 0; i < 10; i++){ 14 if(i == 0 && num.length() == 0){ 15 continue; 16 } 17 num.append(i); 18 trace(num,n); 19 num.deleteCharAt(num.length()-1); 20 } 21 } 22 23 public static void main(String[] args) { 24 List<String> list = printNumbers(3); 25 System.out.println(list.toString()); 26 } 27 }
【补充】大数相加问题
1 class Solution { 2 public String addStrings(String num1, String num2) { 3 int i = num1.length()-1, j = num2.length()-1; 4 int carry = 0; 5 StringBuilder sb = new StringBuilder(); 6 while(i >= 0 || j >= 0 || carry > 0){ 7 if(i >= 0){ 8 carry += num1.charAt(i--)-'0'; 9 } 10 if(j >= 0){ 11 carry += num2.charAt(j--)-'0'; 12 } 13 sb.append(carry%10); 14 carry /= 10; 15 } 16 return sb.reverse().toString(); 17 } 18 }

浙公网安备 33010602011771号