代码随想录 Day24 理论基础 77. 组合

本文介绍了回溯算法的基本原理,如何配合递归用于解决组合、排列、切割、子集和棋盘问题。重点讲解了回溯算法的模板,包括终止条件判断、for循环的选择和递归调用。通过实例说明了终止条件的设定和剪枝优化的重要性。
摘要由CSDN通过智能技术生成

理论基础 

1. 回溯是配合递归算法进行使用的,一般是在递归的下面。回溯的算法是一种暴力的算法,虽然效率并不高,但是常常使用。因为很多时候使用多层for(因为层数实在是套多了)也不能将题目解答,这个时候就需要使用到递归回溯算法。

2. 回溯算法可以解决的问题,回溯算法可以解决组合,排列,切割,子集,棋盘问题,在这些问题上使用回溯算法有着很好的效果。

组合:1234一个四个数,对于他们进行两两组合

排列:对于上述的组合建立一个顺序,进行排列

切割:将一个字符串进行切割成几种情况。

子集:1234一共四个数,去求它的子集。

棋盘问题:就是像是N皇后等。

3. 回溯算法一般都是可以抽象为一棵树

4. 回溯模型的模板:依然是三部曲

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

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

首先是函数和参数:一般是用backtracking(参数)

接下来就是终止情况:进行判断,如果是终止条件的话就存放结果并返回

最后是核心代码去:(这个地方还不是很理解,后面借助于例子再好好理解一下)

for循环就是遍历集合区间,可以理解一个节点有多少个孩子,这个for循环就执行多少次。

backtracking这里自己调用自己,实现递归。

大家可以从图中看出for循环可以理解是横向遍历,backtracking(递归)就是纵向遍历,这样就把这棵树全遍历完了,一般来说,搜索叶子节点就是找的其中一个结果了。

77. 组合

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; i++) {
            path.push_back(i); // 处理节点
            backtracking(n, k, i + 1); // 递归
            path.pop_back(); // 回溯,撤销处理的节点
        }
    }
public:
    vector<vector<int>> combine(int n, int k) {
        result.clear(); // 可以不写
        path.clear();   // 可以不写
        backtracking(n, k, 1);
        return result;
    }
};

思路: 本题的思路还是比较难的,想要理解本题必须要画一棵树

1. 本题的终止条件也是比较难的,借助于树可以理解每次满了k个元素的时候,终止条件就是path每次满了k个元素的时候就是终止的时候。

2. 核心代码区域选择for循环,其中两个元素的第一个元素依次选择四个数中的一个,其实实际上也就是分别有四种情况。并且不断进行弹入,在满足第一个条件也就是达到k个元素的时候就进行终止返回上一层,在for循环中内容有回溯的部分就是pop_back()。

3. 对于组合问题,需要注意的是可以进行剪枝的操作,这样的话就可以使得树的一开始的位置就除去一些不必要处理的情况。

4. 对于递归和for循环的模拟过程是有难度的,好好理解模拟整个过程。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值