递归算法详细解析

article/2025/10/7 4:02:02

递归

程序调用自身的编程技巧称为递归( recursion),它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。一般来说,递归需要有边界条件递归前进段递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。

递归常见形式:

  • 指数型
  • 排列型
  • 组合型

我们以斐波那契数列为例:
1 1 2 3 5 8 13 21 … 即从第三项开始,每一项的值为前两项的和,那么如果我们写成函数的形式的话就是f(n)=f(n-1)+f(n-2),下面我们用代码实现求斐波那契数列第n项的数值

#include<iostream>
using namespace std;int fib(int n){if(n==1 || n==2) return 1;//边界条件return fib(n-1)+fib(n-2);
}int main()
{int n;cin>>n;cout<<fib(n);return 0;
}

每个递归过程都对应一棵递归搜索树

搜索树的每一个枝可以理解为进行了一次递归操作,对于每一层的枝数如果随着问题规模的增长而增长的话可以使用循环结构,如果枝数不随着问题规模的增长而增长的话可以使用顺序递归结构

下面我们通过图示的方式来理解上述过程,我们假设求第五个数及n=5

因为c++代码是一行一行从上向下执行的,当n=5时进入fib(5),此时n!=1 && n!=2,所以继续向下执行,执行到return fib(n-1)+fib(n-2) ,那么就是执行return fib(4)+fib(3);假设是按照从左到右的顺序执行(即先计算fib(4),再计算fib(3))在这里插入图片描述因为我们要计算fib(4)(规模变小了),此时又进入了fib函数,此时n!=1 && n!=2,所以继续向下执行,执行到return fib(n-1)+fib(n-2) ,那么就是执行return fib(3)+fib(2);
在这里插入图片描述按照约定我们要计算fib(3),此时又进入了fib函数,此时n!=1 && n!=2,所以继续向下执行,执行到return fib(n-1)+fib(n-2) ,那么就是执行return fib(2)+fib(1);
在这里插入图片描述
按照约定我们要计算fib(2),此时又进入了fib函数,此时n=2,满足递归结束条件,返回1,此时计算fib(3)时的 return fib(2)+fib(1)这个式子的fib(2)已经返回结果1,下面继续执行fib(1),此时又进入了fib函数,此时n=1,满足递归结束条件,返回1。
在这里插入图片描述

此时fib(3) 的执行语句 return fib(2)+fib(1)这个式子已经执行完毕,return 1+1 ,即fib(3)的结果已经计算为2,将结果返回给上一层。
在这里插入图片描述
此时我们计算f(4)时的return fib(3)+fib(2)式子fib(3)已经计算完毕并将结果2返回,此时继续执行fib(2),因为n=2,满足递归结束条件,将结果1返回,此时fib(4)的return fib(3)+fib(2)已经计算完毕,return 2+1,即fib(4)计算完毕将结果返回上一层(fib的return语句中)。
在这里插入图片描述
此时我们计算f(5)时的return fib(4)+fib(3)式子fib(4)已经计算完毕并将结果3返回,此时继续执行fib(3),按照约定我们要计算fib(3),此时又进入了fib函数,此时n!=1 && n!=2,所以继续向下执行,执行到return fib(n-1)+fib(n-2) ,那么就是执行return fib(2)+fib(1);
在这里插入图片描述
按照约定我们要计算fib(2),此时又进入了fib函数,此时n=2,满足递归结束条件,返回1,此时计算fib(3)时的 return fib(2)+fib(1)这个式子的fib(2)已经返回结果1,下面继续执行fib(1),此时又进入了fib函数,此时n=1,满足递归结束条件,返回1。
在这里插入图片描述
此时计算fib(5)时的return fib(4)+fib(3)式子中fib(4)和fib(3)均已计算完毕,则return 3+2并将结果返回即fib(5)的值为5。
在这里插入图片描述

常见递归形式例题分析:

重要注意事项:
递归(dfs)算法设计最重要的就是顺序,使每种情况都不重不漏。

题目来源acwing

1. 递归实现指数型枚举

从 1∼n 这 n 个整数中随机选取任意多个,输出所有可能的选择方案。

输入格式
输入一个整数 n。

输出格式
每行输出一种方案。

同一行内的数必须升序排列,相邻两个数用恰好 1 个空格隔开。

对于没有选任何数的方案,输出空行。

本题有自定义校验器(SPJ),各行(不同方案)之间的顺序任意。

数据范围
1≤n≤15
输入样例:

3

输出样例:

3
2
2 3
1
1 3
1 2
1 2 3

题目分析:
任意选取多个,即等价为1-n个数,每个数有选或者不选两种情况,一共有2的n次方种情况,且每一种情况这n个数中的每一个数要么选,要么不选。我们从第一个数开始,因为所有的情况中第一个数的选择只有选和不选两种情况。
递归搜索树如下:

在这里插入图片描述

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>using namespace std;const int N = 16;int n;
int st[N];  // 状态,记录每个位置当前的状态:0表示还没考虑,1表示选它,2表示不选它void dfs(int u)
{if (u > n){for (int i = 1; i <= n; i ++ )if (st[i] == 1)printf("%d ", i);printf("\n");return;}st[u] = 2;dfs(u + 1);     // 第一个分支:不选st[u] = 0;  // 恢复现场st[u] = 1;dfs(u + 1);     // 第二个分支:选st[u] = 0;
}int main()
{cin >> n;dfs(1);return 0;
}

2. 递归实现排列型枚举

把 1∼n 这 n 个整数排成一行后随机打乱顺序,输出所有可能的次序。

输入格式
一个整数 n。

输出格式
按照从小到大的顺序输出所有方案,每行 1 个。

首先,同一行相邻两个数用一个空格隔开。

其次,对于两个不同的行,对应下标的数一一比较,字典序较小的排在前面。

数据范围
1≤n≤9
输入样例:

3

输出样例:

1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

题目分析:
当要求字典序的时候,我们从小到大枚举每个数,结果就是字典序。这里我们从位置的角度来思考问题,每个位置应该放哪些数。当第一个位置放1时…,放2时…,放3时…。
递归搜索树如下:
在这里插入图片描述

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>using namespace std;const int N = 10;int n;
int state[N];   // 0 表示还没放数,1~n表示放了哪个数
bool used[N];   // true表示用过,false表示还未用过void dfs(int u)
{if (u > n)  // 边界{for (int i = 1; i <= n; i ++ ) printf("%d ", state[i]); // 打印方案puts("");return;}// 依次枚举每个分支,即当前位置可以填哪些数for (int i = 1; i <= n; i ++ )if (!used[i]){state[u] = i;used[i] = true;dfs(u + 1);// 恢复现场state[u] = 0;used[i] = false;}
}int main()
{scanf("%d", &n);dfs(1);return 0;
}

3. 递归实现组合型枚举

组合型枚举也可以考虑位置,与排列型枚举类似,但是需要一些其他的限制条件

从 1∼n 这 n 个整数中随机选出 m 个,输出所有可能的选择方案。

输入格式
两个整数 n,m ,在同一行用空格隔开。

输出格式
按照从小到大的顺序输出所有方案,每行 1 个。

首先,同一行内的数升序排列,相邻两个数用一个空格隔开。

其次,对于两个不同的行,对应下标的数一一比较,字典序较小的排在前面(例如 1 3 5 7 排在 1 3 6 8 前面)。

数据范围
n>0 ,
0≤m≤n ,
n+(n−m)≤25
输入样例:

5 3

输出样例:

1 2 3 
1 2 4 
1 2 5 
1 3 4 
1 3 5 
1 4 5 
2 3 4 
2 3 5 
2 4 5 
3 4 5 

题目分析:
跟排列的分析方式一样,只不过要求每一行也是字典序,这就需要额外增加限制条件。
递归搜索下如下:
在这里插入图片描述

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>using namespace std;const int N = 30;int n, m;
int way[N];void dfs(int u, int start)//u表示当前选了几个数{if (u + n - start < m) return;  // 剪枝if (u == m + 1){for (int i = 1; i <= m; i ++ ) printf("%d ", way[i]);puts("");return;}for (int i = start; i <= n; i ++ ){way[u] = i;dfs(u + 1, i + 1);way[u] = 0; // 恢复现场}
}int main()
{scanf("%d%d", &n, &m);dfs(1, 1);return 0;
}

全排列剪枝

#include<iostream>
using namespace std;
const int N = 27;
int num[N];
bool judge[N];
int n,m;
void dfs(int u){if(u>m){for(int i=1;i<=m;i++){printf("%d ",num[i]);}cout<<endl;return ;}for(int i=1;i<=n;i++){if(!judge[i]){num[u]=i;if(num[u]>num[u-1])//剪枝{judge[i]=true;dfs(u+1);judge[i]=false;}}}
}
int main()
{cin>>n>>m;dfs(1);return 0;
}

把递归转化为非递归:

因为递归是用栈模拟的,栈是串型的而递归可能是叉型的所以要在非递归的的时候要记录递归时的每个状态(执行到递归的哪一步了)可以用stack来将递归转化为非递归。


http://chatgpt.dhexx.cn/article/RYbqY7E7.shtml

相关文章

递归算法详解

递归&#xff08;英语&#xff1a;recursion&#xff09;在电脑科学中是指一种通过重复将问题分解为同类的子问题而解决问题的方法。 0、前言 递归其实和循环是非常像的&#xff0c;循环都可以改写成递归&#xff0c;递归未必能改写成循环&#xff0c;这是一个充分不必要的条…

递归算法及经典递归实现

递归 递归就是方法自己调用自己&#xff0c;每次调用时传入不同的变量&#xff0c;递归有助于编程者解决复杂的问题&#xff0c;同时可以让代码变得简洁。 递归&#xff1a; 在定义自身的同时又出现了对自身的调用 直接递归函数&#xff1a; 在定义函数体中直接调用自己 间接…

递归算法讲解

原作者&#xff1a;书呆子Rico 《递归的内涵与经典应用》 http://my.csdn.net/justloveyou_ 摘要&#xff1a; 大师 L. Peter Deutsch 说过&#xff1a;To Iterate is Human, to Recurse, Divine.中文译为&#xff1a;人理解迭代&#xff0c;神理解递归。毋庸置疑地&#xff0…

递归算法及经典实例----转载啦~

递归算法及经典递归例子代码实例 递归&#xff08;recursion&#xff09;&#xff1a;程序调用自身的编程技巧。 递归满足2个条件&#xff1a; 1&#xff09;有反复执行的过程&#xff08;调用自身&#xff09; 2&#xff09;有跳出反复执行过程的条件&#xff08;递归出…

递归算法的讲解

原作者&#xff1a;书呆子Rico 《递归的内涵与经典应用》 http://my.csdn.net/justloveyou_ 摘要&#xff1a; 大师 L. Peter Deutsch 说过&#xff1a;To Iterate is Human, to Recurse, Divine.中文译为&#xff1a;人理解迭代&#xff0c;神理解递归。毋庸置疑地&#xff0…

递归算法经典例题及详解

有句话叫递归算法只可意会不可言传&#xff0c;我也领略了&#xff0c;感觉递归算法好神奇&#xff0c;不知不觉的就把工作做完了! 下面这道题也是小编从力扣上看来得&#xff0c;但是关于它是怎样递归的是小编自己想的哦❤️❤️如果有不足&#xff0c;希望大家多多指正&#…

递归算法及经典递归例子代码实现

一、什么叫做递归&#xff1f; 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法&#xff1b; 递归函数就是直接或间接调用自身的函数&#xff0c;也就是自身调用自己&#xff1b; 二、一般什么时候使用递归&#xff1f; 递归时常用的编程技术&#xff0c;其基本…

递归算法(图文详解)

递归算法 一、算法概述 递归算法是一种直接或者间接调用自身函数或者方法的算法。说简单了就是程序自身的调用。二、算法实质 递归算法就是将原问题不断分解为规模缩小的子问题&#xff0c;然后递归调用方法来表示 问题的解。&#xff08;用同一个方法去解决规模不同的问题&am…

递归算法及经典例题详解

大部分人在学习编程时接触的第一个算法应该就是递归了&#xff0c;递归的思想其实很好理解&#xff0c;就是将一个问题拆分为若干个与本身相似的子问题&#xff0c;通过不断调用自身来求解。 但很多新手在实际操作中却很难正确使用到递归&#xff0c;有时面对问题还会有种无从…

几道经典递归算法案例

一&#xff09;递归介绍 定义&#xff1a; 1、在函数体中直接或间接的调用自身的一种方法。 2、必须要有边界值&#xff0c;也就是停止的条件。 头递归&#xff1a;函数调用时不是传递本次计算的结果&#xff0c;而是把当前的调用状态传递&#xff0c;相当于要一直记录上一…

【函数递归】简单递归的5个经典例子,你都会吗?

&#x1f9f8;&#x1f9f8;&#x1f9f8;各位巨佬大家好&#xff0c;我是猪皮兄弟&#x1f9f8;&#x1f9f8;&#x1f9f8; 今天和大家谈谈简单递归&#x1f973;&#x1f973;&#x1f973; &#x1f692;什么是递归 递归的定义&#xff1a; 递归是一种解决问题的有效方…

四个超好用的优质资源搜索网站,海量优质资源等你发现!

在网上找资源的时候总找不到满意的优质资源&#xff1f;今天小编把办公室大佬珍藏多年的四个超好用优质资源搜索网站分享给你&#xff0c;只要你想找&#xff0c;没有找不到的资源&#xff01; 一&#xff0c;学习资料库 学习资料库中有大量的免费学习资料&#xff0c;学习资料…

珍藏多年的技术资源搜索网站——程序员必备

程序员经常需要找一些技术书籍和相关文档&#xff0c;但是通过百度查找往往都是需要各种积分才能够下载&#xff0c;笔者平时的学习中积累几个搜索工具网站&#xff0c;基本上所有需要的技术文档&#xff0c;经典书籍&#xff0c;学习资料&#xff0c;学习视频等等都可以在下列…

在百度上搜不到的资源是在哪找的?就在这些强大的资源搜索网站呀

都说又不懂的问“度娘”最快&#xff0c;但是也有一些东西是在“度娘”哪里也找不到的。那些在百度上搜不到的资源是在哪找的呢&#xff1f;就在这些强大的资源搜索网站呀~ 1.茶杯狐 茶杯狐&#xff0c;它的资源搜索功能很成熟&#xff0c;这里收集了海量的资源可以免费下载&a…

黑科技之资源搜索网站

欢迎加入BIM行业开发交流1群 群号:711844216 一、背景 大家经常会有搜索视频&#xff0c;音乐&#xff0c;PDF&#xff0c;APP等资源的需求&#xff0c;然而通过现有搜索引擎不是很方便找到自己想要的东西&#xff0c;这里笔者推荐几个不错的免费网站&#xff0c;基本上用起来…

超好用的云盘资源搜索网站

超好用的云盘资源搜索网站 云盘资源搜索云云搜索搜百度盘盘搜搜万盘搜索爱挖盘盘搜我的盘 云盘资源搜索 想要的资源轻轻松松一键搞定&#xff0c;让工作生活更轻松。 注*本分享仅供学习参考 云云搜索 http://www.yunyunso.com 搜百度盘 http://www.sobaidupan.com 盘搜…

网盘资源搜索网站

本篇博客总结了百度网盘常用的资源搜索网站。 1.盘搜搜 盘搜搜支持百度云搜索、115网盘、360云盘、华为网盘、新浪微盘等搜索服务&#xff0c;是您工作、学习、娱乐的网盘搜索神器 2.如风搜 如风搜&#xff0c;全网网盘搜索工具。是您工作、学习、娱乐的好助手。找好资源&…

6个超级实用的免费网盘搜索网站分享

因为各种原因&#xff0c;多数网盘搜索网站“寿命”都很短&#xff0c;也有很多百度网盘搜索站点都提高了使用门槛&#xff08;比如付费才能使用&#xff09;。 分享几个自己认为搜索的资料蛮全&#xff0c;到现在&#xff08;2021年&#xff09;为止还能使用的网盘搜索网站。…

我珍藏很久的网盘资源搜索网站和下载神器

摘要&#xff1a;分享几个网盘资源搜索网站和下载神器。 这是「每周分享」的第 17 期。最近有不少新朋友关注&#xff0c;所在再介绍一下这个栏目&#xff0c;每个周末分享一篇 Python 以外的文章&#xff0c;主题涉及&#xff1a;软件、App、PPT、Ps 等几个方面。往期内容你可…

强烈推荐,7个资源搜索网站,从此告别资源付费

前言 周末软件测试自学群很多小伙伴问我&#xff1a;你有啥好的学习资源或者网站没&#xff1f;分享一下可以吗&#xff1f;虽然在国庆期间我整理过&#xff0c;但是趁着周末又给大家整理了一波&#xff0c;完善了不少学习资源&#xff0c;走起~~ 脚本之家 资源很多&#xf…