递归算法整理合集

article/2025/10/7 3:59:27

递归算法整理合集

​递归是常见的算法和编程思想,也是初学者几乎最早接触的算法思想之一。递归算法的优点是代码简洁清晰,逻辑简单易懂;缺点一是算法运行复杂度较高,二是容易在具体代码实现的时候调用栈的层次考虑不周,导致出现错误。但是如果仅仅想实现一个复杂的问题,而不是很关注复杂度的时候,递归算法无疑是一个很好的选择。(实际上,现有的编译器优化很多已经能够自动将递归代码优化为非递归结构实现,因此,如果实用中开启编译器优化,则大多数递归算法的复杂度其实也可以不必考虑)

​本文对递归算法的一些典型题目和例子做了梳理,代码示例有的是用C++,有的是用python,之所以用不同的语言混杂,纯属是具体例题的方便起见,有些地方使用python而不用C++,只是为了更加方便阅读和理解主要思路,而不是过多地关注底层的代码细节。

例题1:斐波拉契数列

​斐波拉契数列是最容易想到的递归算法典例,但是直接递归复杂度为指数级别,很容易即超出时间限制,如果将每次计算的结果变成数组,其思想还是递归的思想,但更改了一种实现方式,则算法复杂度会降低为O(n)量级,代码如下:

class Solution {
public:int fib(int n) {int a[31]={0,1};for(int i=2;i<31;i++){a[i]=a[i-1]+a[i-2];}return a[n];}
};

例题2:全排列问题

​全排列问题是面试中经常会考察的算法题目,即给出一组不重复的数字,要求输出所有的可能的排列。由基础的组合数学知识,我们可以知道,一共有 n ! n! n!种可能的排列,但是如何通过计算机输出呢?

​如果采取递归的思想,容易想到,每个数字作为第一个数字,都会对应 ( n − 1 ) ! (n-1)! (n1)!种排列,即剩下的 ( n − 1 ) (n-1) (n1)个元素的排列数,这样就可以构造递归的结构了,这里用python实现如下:

class Solution:def permute(self, nums: List[int]) -> List[List[int]]:if len(nums)==1:return [nums]if len(nums)==2:return [nums,nums[::-1]]ans = []for a in nums:tmp = copy.deepcopy(nums)# 这里用到deepcopy就是因为python的列表对象直接相等是浅复制,会不对,当然也可以用别的方法去除某元素,比如拼接tmp.remove(a)for i in self.permute(tmp):ans.append([a]+i)return ans

例题3:N皇后问题

​N皇后问题是比较难的递归题目,通常用DFS算法实现,而DFS一般又通过递归实现。

​目前比较简洁和高效的题解是这样的:

qOvyvQ.png

​首先,我们是逐行扫描的,因此不需要考虑行的重合问题;其次,列的重合问题也比较容易考虑,只需要一个长度为N的数组来进行记录即可;最后,需要考虑的是对角线元素,这里不能头大,只需要观察规律,就可以发现对角线元素的特点。对于每一条对角线而言,都是一条截距固定且斜率绝对值为1的直线,因此, i + y i+y i+y的值或者 n − x + y n-x+y nx+y的值必然是固定的,比如过 ( 0 , 1 ) (0,1) (0,1) ( 1 , 0 ) (1,0) (1,0)格子,即构成一个/型对角线,又比如 ( 0 , 2 ) (0,2) (0,2) ( 1 , 3 ) (1,3) (1,3),满足 4 − 0 + 2 = 4 − 1 + 3 4-0+2 = 4-1+3 40+2=41+3,因此也在一条\对角线上。这样有什么好处呢?这样的好处就是对角线是否有值了就可以直接一条对角线用一个 a [ i + j ] a[i+j] a[i+j] a [ n − i − j ] a[n-i-j] a[nij]来记录了,对应的记录对角线的数组应该多大呢?只需要考虑一下边界就可以了。对于/型对角线,可以知道最大的 i + j = n − 1 + 0 = n − 1 i+j = n-1+0=n-1 i+j=n1+0=n1,最小的 i + j = 1 + 0 = 1 > 0 i+j = 1+0=1>0 i+j=1+0=1>0所以只需要长度为 n n n的数组就可以了;对于\型对角线,可以知道最大的 n − i + j = n − 0 + 0 = n n-i+j = n-0+0=n ni+j=n0+0=n,最小的 n − ( n − 1 ) + 0 = 1 + 0 = 1 > 0 n-(n-1)+0 = 1+0=1>0 n(n1)+0=1+0=1>0所以也是只需要长度为 n n n的数组就可以了。

​下面就可以递归了:

​从第一行开始,每一列进行搜索,然后当前这一列和对应的对角线(四角的元素只有一个,其实无所谓对角线)标记为访问过,即为True,之后,就从第二行开始,如果没有冲突,就继续执行此摆放程序,即深度优先搜索DFS,但行数为下一行,如果有冲突,则continue,不再递归,即停止此路径的搜索,相当于DFS剪枝。需要注意的是,由于递归调用了全局变量,因此,每次递归调用后,需要把函数值恢复为原来的值,这一点比较绕,需要注意!代码如下:

class Solution {
public:vector<vector<string>> solveNQueens(int n) {vector<vector<string>> ans;vector<string>board(n,string(n,'.'));vector<bool> col(n,false); //记录列vector<bool> r(n,false);   //记录正对角线vector<bool> l(n,false);   //记录反对角线backtrace(ans,board,col,l,r,0,n);return ans;}void backtrace(vector<vector<string>> &ans,vector<string> &board,vector<bool>  &col,vector<bool>  &l,vector<bool>  &r,int row,int n){if(row==n){ans.push_back(board);return;}for(int j=0;j<n;j++){if(col[j]||r[j+row]||l[n-j+row])continue;col[j]=r[j+row]=l[n-j+row] = true;board[row][j] = 'Q';backtrace(ans,board,col,l,r,row+1,n);//注意此处要恢复原来的值,保存栈现场col[j]=r[j+row]=l[n-j+row] = false;board[row][j] = '.';}}
};

例题4:岛屿数量问题

​岛屿数量问题也是比较常见的算法题,即给出一个01矩阵,要求其中的闭集数量,即1连成片可以构成一个“岛屿”,要求一共有多少个“岛屿”存在。

​这个就不同于上面的DFS了,这个是找到邻居,标记,邻居的邻居也要标记,因此是广度优先搜索,是BFS问题,通过BFS+递归,可以很漂亮地解决这个问题。具体思路是这样的:

​按行按列遍历矩阵的每一个元素,如果元素是0,那是水域,跳过即可;如果这个元素为1说明为陆地,记录数量+1,这个点置为0,同时对此元素BFS递归,即任何于其相邻的1元素在此时都会被搜索到,搜索到怎么办呢?就是把搜索到的邻域的1都置为0,这样统计数量就很容易了。总体思想就是递归+BFS,还有一点并查集的思想。

​代码实现如下:

class Solution:def numIslands(self, grid: List[List[str]]) -> int:n=len(grid)m=len(grid[0])count=0def dfs(x,y):for i,j in [[x+1,y],[x-1,y],[x,y+1],[x,y-1]]:if 0<=i<n and 0<=j<m and grid[i][j]=='1':# 只有搜索到陆地的时候才操作grid[i][j] = '0'dfs(i,j)for i in range(n):for j in range(m):if grid[i][j]=='1':grid[i][j]='0'dfs(i,j)count+=1return count

例题5:二叉树的前中后序遍历

​二叉树的前中后序遍历问题是典型的递归实现算法,不再多言,如下所示:

struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
//前序遍历
void preorder(TreeNode *root,vector<int>&path){if(root){path.push_back(root->val);preorder(root->left,path);preorder(root->right,path);}
}
//中序遍历
void inorder(TreeNode *root,vector<int>&path){if(root){inorder(root->left,path);path.push_back(root->val);inorder(root->right,path);}
}
//后序遍历
void postorder(TreeNode *root,vector<int>&path){if(root){postorder(root->left,path);postorder(root->right,path);path.push_back(root->val);}
}

例题6:N叉树的后序遍历

N叉树的遍历和二叉树其实没有本质的区别,只不过多了个for循环而已,这里以后序遍历为例,看一下代码实现:

/*
// Definition for a Node.
class Node {
public:int val;vector<Node*> children;Node() {}Node(int _val) {val = _val;}Node(int _val, vector<Node*> _children) {val = _val;children = _children;}
};
*/
class Solution {
public://这里必须要分开两个函数调用,否则一个函数要返回值,无法递归vector<int> postorder(Node* root) {vector<int> ret;dfs(ret,root);return ret;}void dfs(vector<int>& ret,Node* root){if(root){for(int i=0;i<root->children.size();i++)dfs(ret,root->children[i]);ret.push_back(root->val);}}
};

例题7:快速幂算法

​著名的快速幂算法常用来计算大指数,广泛应用于密码学等领域。快速幂算法也应用了递归的基本思想,即每次幂为原来的1/2处理,从而以指数级别降幂运算,其实也是递归的思想,代码如下:

def myPow(x, n):if x == 0.0: return 0.0res = 1if n < 0: x, n = 1 / x, -nif n==0:return 1elif n%2==1:return myPow(x,n-1)*xelse:temp = myPow(x,n//2)return temp ** 2

​当然,平时应用的快速幂算法多是非递归位运算实现,但由于本文主要讲解递归算法,就不在这里详细说明了。

​以上就是梳理的一些经典的递归算法例题,供大家参考。


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

相关文章

【关于递归算法的讲解】

递归算法 递归算法的思想 利用递归求解问题的三个特性 递归算法求解的执行过程 递推关系 递归算法的应用举例 小结 递归算法 递归算法是一种通过自身调用自身或间接调用自身来达到问题解决的算法。递归的基本思想是把一个要求解的问题划分成一个或多个规模更小的子问题…

递归算法即案例

递归&#xff08;recursion&#xff09;&#xff1a;程序调用自身的编程技巧。 递归满足2个条件&#xff1a; 1. 有反复执行的过程&#xff08;调用自身&#xff09; 2. 有跳出反复执行过程的条件&#xff08;递归出口&#xff09; 项目中用到递归案例 递归读取文件获取字典…

【递归算法】递归算法的快速入门

&#x1f40b;作者简介&#xff1a;博主是一位.Net开发者&#xff0c;同时还是RPA和低代码平台的践行者。 &#x1f42c;个人主页&#xff1a;会敲键盘的肘子 &#x1f430;系列专栏&#xff1a;数据结构与算法 &#x1f980;专栏简介&#xff1a;图解经典算法&#xff0c;C#代…

递归算法详细解析

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

递归算法详解

递归&#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 盘搜…