[Likou] 77. Combination <backtracking, backtracking pruning>

【Li Button】77. 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.

Example 1:
Input: n = 4, k = 2
Output:

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

Example 2:
Input: n = 1, k = 1
Output:

[[1]]

提示:
1 <= n <= 20
1 <= k <= n

answer

Violent thinking: how much k is equal to how many layers of cycles.

//示例中k为2
int n = 4;
for (int i = 1; i <= n; i++) {
    
    
    for (int j = i + 1; j <= n; j++) {
    
    	
    	sout(i+" "+j);
   	}
}

//示例中k为3
int n = 100;
for (int i = 1; i <= n; i++) {
    
    
    for (int j = i + 1; j <= n; j++) {
    
    
        for (int u = j + 1; u <= n; n++) {
    
    
        	sout(i+" "+j+" "+u);
        }
    }
}

Backtrack

The problems solved by the backtracking method can be abstracted into a tree structure (N-ary tree).

n is equivalent to the width of the tree, and k is equivalent to the depth of the tree. Every time a leaf node is searched in the graph, a result is found.
insert image description here

Three steps of backtracking

  • The return value and parameters of the recursive function

  • Backtracking function termination condition

  • The process of single-level search

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

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

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

    public List<List<Integer>> combine(int n, int k) {
    
    
        backtracking(n, k, 1);
        return result;
    }

    public void backtracking(int n, int k, int startIndex) {
    
    
        // 终止条件
        if (path.size() == k) {
    
    
            //存放结果
            result.add(new ArrayList<>(path));
            return;
        }

        //横向遍历
        for (int i = startIndex; i <= n; i++) {
    
    
            //处理节点
            path.add(i);
            //纵向搜索
            backtracking(n, k, i + 1);
            //回溯,撤销处理结果
            path.removeLast();
        }
    }
}

pruning optimization

insert image description here
The place of pruning is the starting position selected by the for loop of each layer in the recursion. If the number of elements after the starting position selected by the for loop is less than the required number of elements , then there is no need to search.

  • Number of selected elements: path.size();
  • The number of elements still required is: k - path.size();
  • In the set n at most from the starting position: n - (k - path.size()) + 1, start traversing
for (int i = startIndex; i <= n - (k - path.size()) + 1; i++) // i为本次搜索的起始位置
import java.util.*;

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

    public List<List<Integer>> combine(int n, int k) {
    
    
        backtracking(n, k, 1);
        return result;
    }

    public void backtracking(int n  , int k, int startIndex) {
    
    
        // 终止条件
        if (path.size() == k) {
    
    
            //存放结果
            result.add(new ArrayList<>(path));
            return;
        }

        //横向遍历
        for (int i = startIndex; i <= n - (k - path.size()) + 1; i++) {
    
    // i为本次搜索的起始位置
            //处理节点
            path.add(i);
            //纵向搜索
            backtracking(n, k, i + 1);
            //回溯,撤销处理结果
            path.removeLast();
        }
    }
}

Guess you like

Origin blog.csdn.net/qq_44033208/article/details/132403081