The combined sum of the backtracking of the six or six force buckle brush questions

"Continue to create, accelerate growth! This is the sixth day of my participation in the "Nuggets Daily New Plan · June Update Challenge", click to view the details of the event "

foreword

Before, Xiao Liuliu always felt that his algorithm was relatively bad, and it was a shortcoming. In the past, it was really a three-day fishing, two sets of nets, and a few days of brushing, and then slowly stopped, so this Second, with the help of the platform's activities, I plan to start brushing slowly, and I will also summarize the brushing questions, talk about some of my own thinking, and my own ideas, etc. I hope it can be helpful to my friends. You can also take this opportunity to make up for your shortcomings. I hope you can stick to it.

topic

Combination Sum III 216 questions

Find all combinations of k numbers that add up to n and satisfy the following conditions:

Use only numbers 1 to 9 Use each number at most once Returns a list of all possible valid combinations. The list cannot contain the same combination twice, the combinations can be returned in any order.

输入: k = 3, n = 7
输出: [[1,2,4]]
解释:
1 + 2 + 4 = 7
没有其他符合的组合了。
复制代码

analyze

In fact, you can take a look at this problem, which is also solved by the backtracking algorithm. In the past few days, Liuliu shared all the backtracking algorithms. For the definition of the backtracking algorithm, you can read the above article. Take out the template, everyone is like filling in words, try to fill in the code inside,

stencil

Retrospective trilogy

  • 1. Determine the backtracking single-level logic

The number that controls the current position (that is, the current recursive layer) through the for loop can be selected from 1 to 9. Each time a number is selected (for each traversal to a number), we subtract its value from the target sum and add it at the same time Record the set of number combinations; through the previous step, we determined the first digit, and then recursively determined the next digit. It should be noted that the position where the next digit starts when the next layer recursively selects the next digit needs to be updated, because The numbers selected in the previous layer cannot be selected in the next layer; when recursing to a certain layer, we find that k numbers have been determined at this time, and we need to judge whether the sum of these k numbers is equal to n, if it is equal to n , then add the combination collected this time to the final result set and terminate the current layer of recursion, ready to backtrack; otherwise, terminate the recursion directly and prepare to backtrack; when we come out of the previous layer of recursion, it’s time to backtrack, that is, delete Drop the last digit and select a new digit;

  • 2. Determine the backtracking function parameters and return value

According to the above analysis, we can know that we will update the value of the target sum in each layer of recursion, determine whether k numbers are currently selected, and where we must select the starting point of the number in the current layer of recursion. Therefore, the parameters are required: The target sum, the k given by the question, the starting position of the recursive selection number of the current layer Since we will use two global variables to record the current combination and the final result set, there is no need to return a value

  • 3. Determine the termination condition of the backtracking function

When analyzing the single-layer logic, we have already obtained: when we select k numbers, one terminates the current recursion and returns

void backtracking(参数) {
    if (终止条件) {
        存放结果;
        return;
    }

    for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
        处理节点;
        backtracking(路径,选择列表); // 递归
        回溯,撤销处理结果
    }
}

复制代码

answer

package com.six.finger.leetcode.five;


/*
找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:

只使用数字1到9
每个数字 最多使用一次 
返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。
输入: k = 3, n = 7
输出: [[1,2,4]]
解释:
1 + 2 + 4 = 7
没有其他符合的组合了。
 */

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class fifteen {


    public static void main(String[] args) {

        combinationsum(9, 45);

    }

    public static List<List<Integer>> combinationsum(int k, int n) {
        List<List<Integer>> res = new ArrayList<>();

        LinkedList<Integer> path = new LinkedList<>();

        backtracking(res, path, k, n, 1);

        return res;

    }

    private static void backtracking(List<List<Integer>> res, LinkedList<Integer> path, int k, int n, int i) {

        int sum = 0;
        //第一步,递归的退出条件
        for (Integer integer : path) {
            sum = sum + integer;
        }

        if (sum > n) {
            return;
        }

        if (sum == n && path.size() == k) {
            res.add(new ArrayList<>(path));
            return;
        }
        //第二步 树的横向长度,和减枝活动

        for (int j = i; j <= 9 - (k - path.size()) + 1; j++) {
            path.add(j);
            backtracking(res, path, k, n, j + 1);
            path.removeLast();
        }


    }
}
复制代码

image.png

image.png

Looking at the submission record, I'm too lazy to think about how to optimize it

optimization

In fact, why do I have to calculate the sum of paths every time, change it, and calculate it like this

for (int j = i; j <= 9 - (k - path.size()) + 1; j++) {
    sum=sum+i;
    path.add(j);
    backtracking(res, path, k, n, j + 1,sum);
    path.removeLast();
    sum=sum-i;
}
复制代码

image.png

Then it's no use

Finish

Well, this question is over for today. I found that if I practice one type in a row, in fact, this type of question gradually becomes less difficult. I used to think that the algorithm is difficult, but in fact, everything has its own nature. We can only be good at summarizing the rules of the law. Although we can't create anything new, we can still learn from the experience of others. Come on! !

Guess you like

Origin juejin.im/post/7103507614603935780