_21LeetCode代码随想录算法训练营第二十一天-回溯算法

_21LeetCode代码随想录算法训练营第二十一天-回溯算法

题目列表

  • 理论基础
  • 77.组合

理论基础

代码随想录地址:https://programmercarl.com/%E5%9B%9E%E6%BA%AF%E7%AE%97%E6%B3%95%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html

什么是回溯法?

回溯是递归的副产品,只要有递归就会有回溯。

所以以下讲解中,回溯函数也就是递归函数,指的都是一个函数

回溯法的效率

回溯法不是高效的算法。因为回溯的本质是穷举,穷举所有可能,然后选出我们想要的答案。

回溯法解决的问题

  • 组合问题:N个数里面按一定规则找出k个数的集合
  • 切割问题:一个字符串按一定规则有几种切割方式
  • 子集问题:一个N个数的集合里有多少符合条件的子集
  • 排列问题:N个数按一定规则全排列,有几种排列方式
  • 棋盘问题:N皇后,解数独等等

回溯法解决的问题都可以抽象为一颗n叉树。

因为回溯法解决的都是在集合中递归查找子集,集合的大小就构成了树的宽度,递归的深度,都构成的树的深度

回溯法的模板

_21LeetCode代码随想录算法训练营第二十一天-回溯算法_第1张图片

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

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

77.组合

代码随想录地址:https://programmercarl.com/0077.%E7%BB%84%E5%90%88.html

题目

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

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

思路

普通思路

回溯算法通过递归来控制有多少层for循环。

_21LeetCode代码随想录算法训练营第二十一天-回溯算法_第2张图片

每次从集合中选取元素,可选择的范围随着选择的进行而收缩,调整可选择的范围。

图中可以发现n相当于树的宽度,k相当于树的深度。

剪枝优化

_21LeetCode代码随想录算法训练营第二十一天-回溯算法_第3张图片

可以剪枝的地方就在递归中每一层的for循环所选择的起始位置。

如果for循环选择的起始位置之后的元素个数 已经不足 我们需要的元素个数了,那么就没有必要搜索了。

  1. 已经选择的元素个数:path.size();
  2. 还需要的元素个数为: k - path.size();
  3. 在集合n中至多要从该起始位置 : n - (k - path.size()) + 1,开始遍历

代码

/*
 * @lc app=leetcode.cn id=77 lang=cpp
 *
 * [77] 组合
 */

// @lc code=start
class Solution {
private:
    vector<int> path;
    vector<vector<int>> res;
    void backtracking(int n, int k, int start)
    {
        if(path.size() == k)
        {
            res.push_back(path);
            return;
        }
        //i <= n-(k-path.size())+1是剪枝的
        for(int i = start; 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) {
        res.clear();
        path.clear();
        backtracking(n, k, 1);
        return res;
    }
};
// @lc code=end

你可能感兴趣的:(LeetCode刷题笔记,算法,leetcode,c++)