Recursive-Backtracking Algorithm

1. Recursive-Backtracking Algorithm

1. The idea of ​​recursion

Recursion means that the method calls itself, passing in different variables each time it is called.

2. The principle of recursion

1) Every time a method is executed, a space is allocated in [stack memory], which is independent.

2) If it is a [basic data type], the variables in each space are local variables and are [independent] of each other.

3) If it is [reference data type], the variables in each space are [shared], because the address value is stored, and the new objects are stored in [heap memory] and allocated an [address value]. When the method is executed, the same variable will be found in the heap memory based on the variable address value saved in the stack space, because the address values ​​all point to the same one.

4) After each recursion, the conditions must [continuously converge], that is, it must be guaranteed to exit the recursion, otherwise the recursion will not end, and space will continue to be allocated in the stack memory, causing [Stack Overflow] problems.

2. Arrangement problem

1. Arrangement formula

A_n_m = n*(n-1)*(n-2)*...*(n-m+1)=n!/(n-m)!

2. Take A_4_4 = 4 3 2*1=4! For example:

1) Preparation work

1)创建一个集合prelist:[1,2,3,4]

2)创建一个存储排列结果的集合preList

3)定义一个从preList中遍历取元素,然后添加元素到preList集合中的方法:setNum

2) Call the setNum method recursively, including within the method:

1)递归结束的条件:向preList集合中添加4个数,就结束递归,并打印结果

2)判断过程
	【遍历】preList集合,取出preList集合中的第一个元素,如果resList集合中没有该元素,就添加到resList集合;
	否则,继续取出preList集合第二个元素,依次类推,直到元素可以添加到resList集合中。

3)如果经过判断,某个元素添加成功了,则【递归】调用setNum方法,继续添加下一个元素

3) Backtracking

When the [first solution] [1,2,3,4] is successfully found, [return] to the previous stack. At this time, the [top of stack] element is 3. You can also try 4, so again Set the top element of the stack to 4, and then [recursively] set the last number. Obviously, it can only be 3. Therefore, [the second solution] is [1,2,4,3].

After finding the second solution, [Return] to the previous stack, because the number can only be set to 3 or 4, so there is no other choice, [Continue to fall back] to the previous stack, the current number is 2, still You can choose 3 or 4, so set it to 3 first, and then [recursively] set other numbers; set it to 4, and set other numbers recursively.

In the end, [all the arrangement results with the first element being 1 are found] in the resList collection.

Then set 2 as an element of resList, you can find all the permutation results starting with 2, and so on, find those starting with 3 and 4.

4) The order in which the final results are printed is the order analyzed above, that is:

[1,2,3,4]
[1,2,4,3]
[1,3,2,4]
[1,3,4,2]

5) Note: When going back to the previous stack, the reason why you can try other numbers is because the prelist array is [traversed] every time you recurse.

3.Java code

public class Permutation {
    
    

    static Stack<Integer> stack = new Stack<>();

    public static void main(String[] args) {
    
    

        int res = permutation(4, 3);
        System.out.println("A_4_3的结果为:" + res);

        List<Integer> preList = new ArrayList<>();
        preList.add(1);
        preList.add(2);
        preList.add(3);
        preList.add(4);
        System.out.println("preList=" + preList);

        enumerration(preList, 4, 0);
    }

    /**
     * 全排列公式实现
     * @param n 一共有n个
     * @param m 从n中取m个
     * @return 表示一共有多少种取法
     */
    public static int permutation(int n, int m){
    
    
        int res = 1;
        /*
            A_4_2 = 4 * 3   循环两次实现:4*1*3
            A_4_3 = 4 * 3 * 2   循环三次实现:4*1*3*2
            A_n_m   需要循环m次实现:n*1*(n-1)*...*(n-m+1)
         */
        for (int i = 0; i < m; i++) {
    
    
            res *= n;
            n--;
        }
        return res;
    }

    /**
     * 列举出排列结果
     * 例如A_4_4,排列结果就是在给的四个数中依次不重复地选择一个数
     * @param preList 存放需要排列的数据的列表
     * @param total 表示一共选几次数
     * @param cur 表示当前是第几次选数
     */
    public static void enumerration(List<Integer> preList, int total, int cur){
    
    
        if (cur == total){
    
    
            System.out.println(stack);
            return;
        }
        for (Integer item : preList) {
    
    
            if (!stack.contains(item)){
    
    
                stack.push(item);
                enumerration(preList, total, cur+1);
                stack.pop();
            }
        }
    }
}

3. The Eight Queens Problem

1.Problem description

Any two queens cannot be in the same row, column or diagonal. How many ways are there?

Following the idea of ​​sparse arrays, we compress the chessboard represented by a two-dimensional array into a one-dimensional array.
arr[i]=value. i represents the i+1th queen, and value represents that this queen should be placed in the i+1th row and i+1th column.

2. Idea analysis

1) Similar to the permutation problem, first place the first queen in the first row and first column, and then call the method of placing the queen recursively until the first correct solution is generated.

2) When the first correct solution is generated, go back to the previous stack (i.e., the second to last row), try other positions, then call the method of placing the queen, set the queen of the last row, and so on, and finally find it. All correct solutions for placing the first queen in the first row and first column

3) Then place the first queen in the first row and second column. . .

3.Java code

在这里插入代码片

Guess you like

Origin blog.csdn.net/weixin_42214237/article/details/123392907