Combination problem of backtracking algorithm

Combination problem: Find a set of k numbers in N numbers according to certain rules. The following is a common backtracking algorithm topic to solve the combination problem.
leedcode77. Combination
Given two integers n and k, return all possible combinations of k numbers in the range [1, n].
You can return answers in any order.

insert image description here
After the backtracking method is abstracted into a tree structure, the traversal process is: for loop horizontal traversal, recursive vertical traversal, and backtracking to continuously adjust the result set.
insert image description here

class Solution {
    
    
    //回溯算法
    public List<List<Integer>> combine(int n, int k) {
    
    
     
      //List<Integer> path=new ArrayList<>();
      Deque<Integer> path=new LinkedList<>();
      List<List<Integer>> res=new ArrayList<>();

      dfs(n,k,1,path,res);
      return res;
    }

    public void dfs(int n,int k,int startIndex,  Deque<Integer>  path,List<List<Integer>> res){
    
    
       if(path.size()==k){
    
    
           //终止条件
           res.add(new ArrayList<>(path));
           return;
       }
       //控制树的横向遍历
       for(int i=startIndex;i<=n-(k-path.size())+1;i++){
    
    //剪枝处理
           path.add(i);
           dfs(n,k,i+1,path,res);
           path.removeLast();//回溯,弹出处理的节点
       }
    }
}

leedcode216 Combined sums III
Find all combinations of k numbers whose sum is n, and satisfy the following conditions:

Use only the digits 1 to 9
Use each digit at most once
Return a list of all possible valid combinations. The list cannot contain the same combination twice, and the combinations may be returned in any order.

Example 1:

Input: k = 3, n = 7 Output: [[1,2,4]] Explanation: 1 + 2 + 4 = 7 There are no other matching combinations.

Example 2:

Input: k = 3, n = 9 Output: [[1,2,6], [1,3,5], [2,3,4]] Explanation: 1 + 2 + 6 = 9 1 + 3 +
5 = 9 2 + 3 + 4 = 9 There are no other matching combinations.

Example 3:

Input: k = 4, n = 1 Output: [] Explanation: No valid combination exists.
Using 4 different numbers in the range [1,9], the smallest sum we can get is 1+2+3+4 = 10, since 10 > 1, there is no valid combination.

class Solution {
    
    
    List<List<Integer>> result=new ArrayList<>();
    Deque<Integer> path=new LinkedList<>();

    public List<List<Integer>> combinationSum3(int k, int n) {
    
    
          
          dfs(k,n,1,0);
          return result; 
    }

    public void dfs(int k,int n,int startIndex,int sum){
    
    
          
        //剪枝
         if(sum>n){
    
    
             return;
         }
        if(k==path.size()){
    
    
            if(sum==n){
    
    
                result.add(new ArrayList<>(path));
                return;
            }
        }

        for(int i=startIndex;i<=9-(k-path.size())+1;i++){
    
    
            path.add(i); 
            sum=sum+i;
            dfs(k,n,i+1,sum);
            path.removeLast();
            sum=sum-i;
        }

    }
}

leedcode46. Full permutation
Given an array nums without repeated numbers, return all possible permutations. You can return answers in any order.

Example 1:

Input: nums = [1,2,3] Output: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1 ,2],[3,2,1]]

Example 2:

Input: nums = [0,1] Output: [[0,1],[1,0]]

Example 3:

Input: nums = [1] Output: [[1]]

leedcode17. Alphabet combination of phone number
Given a string containing only digits 2-9, return all the letter combinations it can represent. Answers can be returned in any order.

The mapping of numbers to letters is given as follows (same as for phone keys). Note that 1 does not correspond to any letter.
insert image description here
Example 1:

Input: digits = "23"
Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]

Example 2:

input: digits=""
output: []

Example 3:

Input: digits = "2"
Output: ["a", "b", "c"]

If it is a set to find a combination, startIndex is needed.
If multiple collections are combined and each collection does not affect each other, then startIndex is not used.
In this question, multiple collections are combined, so startIndex is not used, and each time starts from i=0.

class Solution {
    
    
     private List<String> res= new ArrayList<>();
    public List<String> letterCombinations(String digits) {
    
    
        if(digits.length()==0||digits==null){
    
    
            return res;
        }
       //0和1无效,2到9有效
        String[] s={
    
    "","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
        //res = new ArrayList<>();
        isBackTest(s,digits,0);
        return res;
    }
     //涉及字符串拼接可以使用StringBuilder
    StringBuilder temp=new StringBuilder();
    //三个参数分别是字符串s,要组合的字符digits,和组合的个数num
    private void isBackTest(String[] s, String digits, int num) {
    
    
        if(num==digits.length()){
    
    //如果要组合的字符长度等于组合个数直接添加并返回
       //     System.out.println("进来");
            res.add(temp.toString());
            return;
        }
        //System.out.println("再进来");
        String str=s[digits.charAt(num)-'0'];//比如digits="23",我们可以获取'2'-'0'=2,'3'-'0'=3
        for(int i=0;i<str.length();i++){
    
    
            temp.append(str.charAt(i));//添加字符串中的字符
            isBackTest(s,digits,num+1);//递归
            temp.deleteCharAt(temp.length()-1);//回溯,减去末尾的元素,此时的num是当前方法的num
        }
    }
}

leedcode39. Combined sum
Given an integer array candidates without repeated elements and a target integer target, find out all the different combinations in candidates that can make the number sum target number target, and return it in the form of a list. You can return these combinations in any order.

The same number in candidates can be selected repeatedly without limit. Two combinations are different if the chosen number of at least one number is different.

For a given input, the number of different combinations that sum to target is guaranteed to be less than 150.

Example 1:

Input: candidates = [2,3,6,7], target = 7 Output: [[2,2,3],[7]]
Explanation: 2 and 3 can form a set of candidates, 2 + 2 + 3 = 7 . Note 2 can be used multiple times. 7 is also a candidate, 7 = 7 . There are only these two combinations.

Example 2:

Input: candidates = [2,3,5], target = 8
Output: [[2,2,2,2],[2,3,3],[3,5]]

Example 3:

Input: candidates = [2], target = 1
Output: []

There are two differences between this question and the 77. Combination 216. Combination Sum III we talked about before:

  • There is no quantity requirement for the combination
  • Elements can be selected infinitely
class Solution {
    
    
  public List<List<Integer>> combinationSum(int[] candidates, int target) {
    
    
  //先排好序后面如果有大于target可以直接返回
        Arrays.sort(candidates);
        
        //相比与组合III,这道题增加了同一个元素可以被无限重复选取,还有就是递归结束条件不是第几层而是大于等于target
        isBackTest(candidates,target,0,0);
        return res;
    }
    List<List<Integer>> res=new ArrayList<>();
    List<Integer> path=new ArrayList<>();
    private void isBackTest(int[] candidates, int target, int startIndex,int sum) {
    
    

       if(sum>target){
    
    
           return;
       }
        if(sum==target){
    
    
            res.add(new ArrayList<>(path));
            return;
        }
     //剪枝条件不符合sum+candidates[i]<=target,连递归都不需要调
        for(int i=startIndex;i<candidates.length&&sum+candidates[i]<=target;i++){
    
    
            sum=sum+candidates[i];
            path.add(candidates[i]);
            isBackTest(candidates,target,i,sum);//这里不用i+1,表示可以重复读取当前的数
            path.remove(path.size()-1);//回溯
            sum=sum-candidates[i];
        }
    }
}

leedcode40. Combined sums II
Given a set of candidate numbers candidates and a target number target, find out all the combinations in candidates that can make the sum of numbers into target.

Each number in candidates can only be used once in each combination.

Note: A solution set cannot contain duplicate combinations.

Example 1:

Input: candidates = [10,1,2,7,6,1,5], target = 8,
output: [ [1,1,6], [1,2,5],[1,7], [ 2,6] ]

Example 2:

Input: candidates = [2,5,2,1,2], target = 5,
output: [ [1,2,2], [5] ]

The difference between this question and 39. Combined sum is as follows:
each number in the candidates of this question can only be used once in each combination.
The elements of the array candidates in this question are repeated, and the sum of 39. combinations is an array of candidates without repeated elements.
Finally, this question is the same as 39. The requirements for the sum of combinations are the same, and the solution set cannot contain repeated combinations.
The difficulty of this question is that the collection (array candidates) has repeated elements, but it cannot have repeated combinations.

class Solution {
    
    
 public List<List<Integer>> combinationSum2(int[] candidates, int target) {
    
    
        //先进行排序
        Arrays.sort(candidates);
        //新建一个used数组,用来进行标记和去重
        boolean[] used = new boolean[candidates.length];
        isBackTest(candidates, target, 0, 0, used);
        return result;
    }
    List<List<Integer>> result=new ArrayList<>();
    List<Integer> path=new ArrayList<>();
    private void isBackTest(int[] candidates, int target, int sum, int statIndex, boolean[] used) {
    
    
        // if(sum>target){//已经在for循环的之后进行剪枝了,不会进入递归也不用写这条语句
        //     return;
        // }
        if(sum==target){
    
    
            result.add(new ArrayList<>(path));
            return;
        }
        for(int i=statIndex;i<candidates.length&&candidates[i]+sum<=target;i++){
    
    
            if(i>0&&candidates[i]==candidates[i-1]&&used[i-1]==false){
    
    //去重
            //递归回溯过程可以看成树结构
            //used[i - 1] == true,说明同一树枝candidates[i - 1]使用过
            //used[i - 1] == false,说明同一树层candidates[i - 1]使用过
            //如果当前一个元素和上一个元素(相邻)相同,并且上一个元素的used[i]为false,
            //直接continue进行下次循环
                continue;
            }
            path.add(candidates[i]);
            sum=sum+candidates[i];
            used[i]=true;//代表已经标记为true
            isBackTest(candidates,target,sum,i+1,used);
            //回溯
            path.remove(path.size()-1);
            sum=sum-candidates[i];
            used[i]=false;//更新标记为false
        }
    }
}

Guess you like

Origin blog.csdn.net/ChenYiRan123456/article/details/128841691
Recommended