递归的本质与基本实现形式

简介: 递归的本质与基本实现形式


递归Recursion

如何理解递归?

  • 函数自身调用自身
  • 通过函数体来进行的循环
  • 以自相似的方法重复进行的过程

计算n!

n! = 1* 2* 3* …* n

def factorial(n):
  if n <= 1:
    return 1
  return n * factorial(n - 1)

啊喂,求n!用递推它不香吗…

确实,因为n!的推导路径我们已经知道了,for一遍就好了。

但如果是不太容易找到推导路径的问题呢?

比如下面的问题,一棵树,在根节点的时候,我们是不知道下边长什么样的…

递归的三个关键:

  • 定义需要递归的问题(重叠子问题)——数学归纳法思维
  • 确定递归边界
  • 保护与还原现场

C++/Java代码模板

void recursion(int level, int param) {
  // terminator
  if (level > MAX_LEVEL) {
    // process result
    return; 
  }
  // process logic in current level
  process(level, param);
  // drill down
  recur(level + 1, new_param);
  // restore the current level status
}

Python代码模板

def recursion(level, param1, param2, ...):
  # recursion terminator
  if level > MAX_LEVEL: 
    # process result
    return
  # process logic in current level
  process(level, data...) 
  # drill down
  self.recursion(level + 1, new_param1, ...) 
  # restore the current level status if needed

实战

78.子集

https://leetcode.cn/problems/subsets/

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        n = nums.size();
        recur(nums,0);
        return ans;
    }
private:
    void recur(vector<int>& nums, int i){
        if(i == n){
            ans.push_back(chosen);
            return;
        }
        recur(nums, i + 1);
        chosen.push_back(nums[i]);
        recur(nums, i + 1);
        chosen.pop_back();
    }
    int n;
    vector<int> chosen;
    vector<vector<int>> ans;
};

77.组合

https://leetcode.cn/problems/combinations/

class Solution {
public:
    vector<vector<int>> combine(int n, int k) {
        this->n = n;
        this->k = k;
        recur(1);
        return ans;
    }
private:
    void recur(int i) {
        if(chosen.size() > k || chosen.size() + (n - i + 1) < k) return;
        if(i == n + 1){
            ans.push_back(chosen);
            return;
        }
        recur(i + 1);
        chosen.push_back(i);
        recur(i + 1);
        chosen.pop_back();
    }
    int n, k;
    vector<int> chosen;
    vector<vector<int>> ans;
};

46.全排列

https://leetcode.cn/problems/permutations/

class Solution {
public:
    vector<vector<int>> permute(vector<int>& nums) {
        n = nums.size();
        used = vector<bool>(n, false);
        recur(nums, 0);
        return ans;
    }
private:
    void recur(vector<int>& nums, int pos) {
        if(pos == n){
            ans.push_back(a);
            return;
        }
        for(int i = 0; i < n; i++){
            if(!used[i]){
                a.push_back(nums[i]);
                used[i] = true;
                recur(nums, pos + 1);
                used[i] = false;
                a.pop_back();
            }
        }
    }
    vector<bool> used;
    vector<int> a;
    int n;
    vector<vector<int>> ans;
};

47.全排列 ||

https://leetcode.cn/problems/permutations-ii/

class Solution {
public:
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        vector<vector<int> > res;
        do{
            res.emplace_back(nums);
        }while(next_permutation(nums.begin(), nums.end()));
        return res;
    }
};

递归基本形式总结

以上问题都是递归实现的“暴力搜索”(或者叫枚举、回溯等)

可以总结为以下三种基本形式

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,立即学习

相关文章
|
2月前
|
存储 C++
定义一堆数组
定义一堆数组
9 1
|
3月前
|
存储 Java 程序员
Java数组全套深入探究——基础知识阶段2、数组的定义语法
Java数组全套深入探究——基础知识阶段2、数组的定义语法
29 0
|
3月前
|
存储 传感器 机器学习/深度学习
Java数组全套深入探究——进阶知识阶段6、三维数组以及更多维度数组的概念和用法
Java数组全套深入探究——进阶知识阶段6、三维数组以及更多维度数组的概念和用法
46 0
|
4月前
|
机器学习/深度学习 编译器 C语言
关于函数递归的基础
关于函数递归的基础
33 5
|
11月前
|
存储 编译器 程序员
C/C++(数组概念)
C/C++(数组概念)
|
数据可视化 算法
大白话理解递归本质,可视化递归过程
大白话理解递归本质,可视化递归过程
154 0
通过代码加解析的方式带领大家分析 :数组与指针的关系
通过代码加解析的方式带领大家分析 :数组与指针的关系
59 0
通过代码加解析的方式带领大家分析 :数组与指针的关系
比较(用函数方法)打印100到200之间的单数,素数,并且请教各位读者,如何区别的不同
比较(用函数方法)打印100到200之间的单数,素数,并且请教各位读者,如何区别的不同
80 0
比较(用函数方法)打印100到200之间的单数,素数,并且请教各位读者,如何区别的不同
数据结构与算法__01--单链表无顺序添加时,节点对象形成封闭环问题,无法添加同一个对象导致遍历输出时一直执行输出
单链表无顺序添加时,节点对象形成封闭环问题,无法添加同一个对象导致遍历输出时一直执行输出