代码随想录day24

发布时间:2024年01月19日

回溯算法?

????????回溯的本质是穷举,穷举所有可能,然后选出我们想要的答案,如果想让回溯法高效一些,可以加一些剪枝的操作。

????????回溯法,一般可以解决如下几种问题:

? ? ? ? 1、组合问题:N个数里面按一定规则找出k个数的集合

? ? ? ? 2、切割问题:一个字符串按一定规则有几种切割方式

? ? ? ? 3、子集问题:一个N个数的集合里有多少符合条件的子集

? ? ? ? 4、排列问题:N个数按一定规则全排列,有几种排列方式

? ? ? ? 5、棋盘问题:N皇后,解数独等等

回溯法模版:

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

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

77. 组合

给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。

示例: 输入: n = 4, k = 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]

? ? ? ? 根据模版,得出代码:

class Solution {
public:
    vector<vector<int>> res;
    vector<int> path;
    void backtravel(int n,int k,int start){
        if(path.size()==k){
            res.push_back(path);
            return;
        }
        for(int i=start;i<=n;++i){
            path.push_back(i);//处理节点
            backtravel(n,k,i+1);//递归
            path.pop_back();//回溯
        }
    }
    vector<vector<int>> combine(int n, int k) {
        backtravel(n,k,1);
        return res;
    }
};

????????配合剪枝操作进行优化:如果for循环选择的起始位置之后的元素个数 已经不足 我们需要的元素个数了,那么就没有必要搜索了。所以起始位值至多从n-(k-path.size())+1开始。

class Solution {
public:
    vector<vector<int>> res;
    vector<int> path;
    void backtravel(int n,int k,int start){
        if(path.size()==k){
            res.push_back(path);
            return;
        }
        for(int i=start;i<=n-(k-path.size())+1;++i){
            path.push_back(i);//处理节点
            backtravel(n,k,i+1);//递归
            path.pop_back();//回溯
        }
    }
    vector<vector<int>> combine(int n, int k) {
        backtravel(n,k,1);
        return res;
    }
};

文章来源:https://blog.csdn.net/hndgfnd/article/details/135701587
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。