【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 }

 

posted @ 2020-06-06 12:32  xd会飞的猫  阅读(192)  评论(0)    收藏  举报