代码随想录算法训练营Day24|回溯基础理论、组合

回溯基础理论

递归函数下面,纯暴力搜索出结果。

回溯可以解决的问题有

组合问题:在集合中满足条件的小组合

切割问题:问满足条件的字符串的切割方式

求子集个数

排列问题:强调元素的顺序,组合不讲究这个顺序,只看元素。

棋盘问题:n皇后问题

回溯可以抽象为图形结构,抽象为树形结构,n叉树,横向:宽度即集合大小,纵向:深度即递归的深度。

递归函数:

void backtracking(){

if(终止条件){

收集结果,//在叶子节点收集结果,每一轮都收集

return;

}

for(遍历集合元素)

{

处理节点的逻辑;

递归;

回溯,撤销处理结果;//14,撤销4放3得到13,撤销3放2得到12

}

}

组合

回溯三部曲:

1.递归函数的参数和返回值。

2.确定递归的终止条件。

3.确定单层搜索的逻辑。

vector<vector<int>>result; //二维数组,定义为全局变量,最后需要一个大组合把所有小组合以结果集方式返回回去。

vector<int>path;//用来存放符合条件的单一结果

void backtracking(int n,int k,int startIndex)//递归函数

{ }

终止条件:

if(path.size() == k){//k为组合大小,到达叶子节点

result.push_back(path);//收割结果

return;

}

//单层处理逻辑,处理节点,回溯

for(int i = startIndex; i <=n; i++){

path.push_back(i);//处理节点

backtracking(n,k,i+1);//递归,例如从14变21,需要从第一层变为第二层。

path.pop_back();//回溯,例如从12变13,变14,需要把前一个pop释放出去。

}

剪枝优化

每一层for循环进行一次剪枝,剪去不必要的子孩子。

缩小上面单层循环i的大小。

i=startIndex;i<=n;改为i<   n -(k-path.size())+1    //此时是左闭右开,从startIndex开始,如果不用左闭右开,视情况而定。至多从n -(k-path.size())开始。

class Solution {
private:
    vector<vector<int>> result;//二维,存放所有结果的集合
    vector<int> path;//一维,存放单层符合条件的结果
    void backtracking(int n, int k, int startIndex) {
        if (path.size() == k) {
            result.push_back(path);
            return;
        }
        for (int i = startIndex; i <= n - (k - path.size()) + 1; i++) { // 注意优化
            path.push_back(i); // 处理节点
            backtracking(n, k, i + 1);
            path.pop_back(); // 回溯,释放撤销处理的节点
        }
    }
public:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值