递归调用

算法图解——递归

大憨熊 提交于 2020-02-18 05:28:09
递归 函数自己调用自己 在用递归的同时,也可以用while循环实现 递归只是让解决方案更加清晰,并没有性能上的优势,有时候甚至循环的性能更好 “如果使用循环,程序性能可能更高;如果使用递归,程序可能更容易理解” 基线条件和递归条件 编写递归函数时,必须告诉他停止的条件 基线条件:函数不再调用自己即停止 递归条件:调用自己 def countdown ( i ) : print ( i , end = ' ' ) if i <= 1 : # 基线条件 return else : # 递归条件 countdown ( i - 1 ) countdown ( 10 ) 10 9 8 7 6 5 4 3 2 1 来源: CSDN 作者: 我是小杨我就这样 链接: https://blog.csdn.net/weixin_44478378/article/details/104361158

php递归函数--遍历

倖福魔咒の 提交于 2020-02-17 23:31:16
多应用在 栏目多级、无限极调用 数据库数据如: id catname pid 1 关于我们 0 2 新闻 0 3 公司新闻 2 4 行业动态 2 select读出数据后整理函数 $cate function digui($cate,$pid=0){   foreach($cate as $v){     if($v['pid']==$pid){       $v['child'] = digui($cate,$v['id']);       $arr[] = $v;     }   } return $arr; } 相当于不断在循环整个$cate数组。。 遍历html代码 1 <foreach name="cate" item='app'> 2 <div class="app"> 3 <p> 4 <strong>{$app.catname}</strong> 8 </p> 9 <foreach name="app.child" item='action'> 10 <dl> 11 <dt> 12 <strong>{$action.catnaem}</strong> 16 </dt>24         </dl> 25           </foreach> 26         </div> 27       </foreach> 来源: https://www.cnblogs

如何k个一组反转链表

本小妞迷上赌 提交于 2020-02-17 10:58:32
之前的文章「递归反转链表的一部分」讲了如何递归地反转一部分链表,有读者就问如何迭代地反转链表,这篇文章解决的问题也需要反转链表的函数,我们不妨就用迭代方式来解决。 本文要解决「K 个一组反转链表」,不难理解: 这个问题经常在面经中看到,而且 LeetCode 上难度是 Hard,它真的有那么难吗? 对于基本数据结构的算法问题其实都不难,只要结合特点一点点拆解分析,一般都没啥难点。下面我们就来拆解一下这个问题。 一、分析问题 首先,前文 学习数据结构的框架思维 提到过,链表是一种兼具递归和迭代性质的数据结构,认真思考一下可以发现 这个问题具有递归性质 。 什么叫递归性质?直接上图理解,比如说我们对这个链表调用 reverseKGroup(head, 2) ,即以 2 个节点为一组反转链表: 如果我设法把前 2 个节点反转,那么后面的那些节点怎么处理?后面的这些节点也是一条链表,而且规模(长度)比原来这条链表小,这就叫 子问题 。 我们可以直接递归调用 reverseKGroup(cur, 2) ,因为子问题和原问题的结构完全相同,这就是所谓的递归性质。 发现了递归性质,就可以得到大致的算法流程: 1、先反转以 head 开头的 k 个元素 。 2、将第 k + 1 个元素作为 head 递归调用 reverseKGroup 函数 。 3、将上述两个过程的结果连接起来 。

递归函数的使用及注意事项

两盒软妹~` 提交于 2020-02-16 03:15:11
#递归函数:函数内调用自身的函数(俄罗斯套娃) 举例:求4的阶乘 分析: 4! = 4 * 3! 3! = 3 * 2! 2! = 2 * 1! 1! = 1 先定义函数,只有当num 为1时,是他本身,所以只有这一个特例而已,用if写出来,其余的情况用else写。 >> def rec ( num ) : >> if num == 1 : >> return 1 >> else : >> return num * rec ( num - 1 ) >> result = rec ( 4 ) >> print ( result ) 24 不知道else后怎么写,怎么办? : 函写到数第五行的时候,可以用2!来举特例。2! = 2 * 1! 先写成: return 2 * rec(1) 然后用变量num替换掉数值,变成 return num * ruc (num - 1) 注意: 递归函数容易造成死循环,原因是没有结束递归的条件,而且会造成栈溢出。 在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。 拓展: import sys #设置递归次数 sys.setrecursionlimit = 1000 #最多递归1000次 #获取递归次数

栈与递归

谁说我不能喝 提交于 2020-02-16 00:06:38
文章目录 递归 函数调用 递归工作栈 递归算法的效率分析 递归转换为非递归 递归算法优点 递归 若在一个函数、过程或数据结构定义的内部又直接(或间接)出现定义本身的应用,则称它们是递归。 三种常使用递归的情况: 定义是递归的 例1:阶乘函数 long Fact ( long n ) { if ( n == 0 ) return 1 ; //递归终止的条件 else return n * Fact ( n - 1 ) ; //递归步骤 } 例2:Fibonacci数列 long Fib ( long n ) { if ( n == 1 || n == 2 ) return 1 ; //递归终止的条件 else return Fib ( n - 1 ) + Fib ( n - 2 ) ; //递归步骤 } 分解-求解的策略称为 分治法 采用分治法进行递归求解问题需要满足的条件: (1)能将一个问题转变成一个新问题,而新问题与原问题的解法相同或类同,不同的仅是处理的对象,并且这些处理对象更小且变化有规律 (2)可以通过上述转化而使问题简化 (3)必须有一个明确的递归出口,或称递归的边界 分治法: void p ( 参数表 ) { if ( 递归结束条件成立 ) 可直接求解; //递归终止条件 else p ( 较小的参数 ) ; //递归步骤 } 数据结构是递归的

LeetCode.509——斐波那契数

点点圈 提交于 2020-02-14 21:05:41
问题描述: 斐波那契数,通常用 F(n) 表示,形成的序列称为斐波那契数列。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是: F(0) = 0, F(1) = 1 F(N) = F(N - 1) + F(N - 2), 其中 N > 1. 给定 N,计算 F(N)。 示例 : 输入:2 输出:1 解释:F(2) = F(1) + F(0) = 1 + 0 = 1. 问题分析: 由于计算任何一个第n(n >= 2)项的数都需要知道其前面两个数,即需要知道n-1和n-2是多少,然后两个相加得到结果,但是问题来了,要知道n-1,就要需要知道n-2,要知道n-2就需要知道n-3,会一直这样的循环递归下去,一直到第一个数,第二个,第三个.......再反推回来。 那就很明显了,大家第一时间想到的方法便是递归,就下来实现一下: 方法一:递归实现 public class Solution { public int fib(int n) { if(n <= 1){ return n; } return fib(n-1) + fib(n-2); } } ​ 问题分析: ​ 先看一下递归图: ​ 由于很多数的计算都要重复很多次,效率并不高,时间复杂度达到了 O(2^n),是斐波那契数计算中 时间复杂度最大,最不可取的方法。 ​ 空间复杂度:O(n),堆栈中需要的空间与 N

JC2 递推,递归与分治

喜欢而已 提交于 2020-02-14 01:43:06
递推,递归与分治 递推 什么是递推 递推,就是从小的解开始,一步一步推到最优解的过程。 如何递推 这就要看具体情况,想出递推式,然后一步一步递推即可。 递推如何应用 讲这个之前,我们不妨先讲一讲递推如何具体实现。 第一步是先 初始化 。切记! 有两种表示方法: 数组递推法,如 f[i] = f[i-1]+f[i-2]; 记忆化搜索,若冗余状态比较多则需要记忆化,否则直接调用即可。注意递归的结束,否则MLE或TLE后果自负。 那么,什么是冗余状态呢? 这是一个关于f(5)的解答树,可以看见,红色的都是被重复计算的,很多节点被重复计算了多次,若数比较大,重复计算的可不止这几个,而是一颗巨大的子树。 我们在计算时用数组记录已经算出的结果,就是记忆化搜索的核心思想。 来源: https://www.cnblogs.com/lhy-cblog/p/12306015.html

递归、尾递归和使用Stream延迟计算优化尾递归

ε祈祈猫儿з 提交于 2020-02-13 10:41:58
我们在学数据结构的时候必然会接触栈(Stack),而栈有一个重要的应用是在程序设计语言中实现递归。递归用途十分广泛,比如我们常见的阶乘,如下代码: 1234 public static int (int n) { if (n == 1) return 1; return n * func1(n - 1);} 就可以用递归实现,而且实现相当简洁。如果要计算n的阶乘,那么只需知道n-1的阶乘再乘以n,同理依次类推,直到当我们计算2的阶乘的时候,只需知道1的阶乘,显然这是递归终止条件,再层层向上返回,直至计算出n的阶乘即可。 从上面的分析可以看出,如果我们要进行递归求解某一问题,需要满足以下两个条件: 能将一个问题转变为另一个新问题,而新问题的解法与原问题相同或者类同,并且新问题的数据规模更小,问题简化。 使用递归的情景是当前数据规模较大,直接计算比较困难,那么可以将该问题进行分解,数据规模越来越小,计算也越来越容易,其实这是“分治法”的体现。 存在递归终止条件,或者说递归的边界。 递归的终止条件是必须的,既然当前问题可以分解,那么就必须存在一个“极限”,分解到什么程度?到哪里停止? “分治法”求解递归问题算法有一个一般形式: 1234 void p(参数列表) { if (递归终止条件成立) 直接求解; // 递归终止条件 else p(较小的参数) // 递归步骤}

C#-TreeView加载(递归)

故事扮演 提交于 2020-02-13 03:07:58
文件资料递归加载: private void frmMain_Load ( object sender , EventArgs e ) { string demopath = Path . Combine ( Path . GetDirectoryName ( Assembly . GetExecutingAssembly ( ) . Location ) , "deom" ) ; //所有文件的根目录 LoadData ( demopath , treeView1 . Nodes ) ; } //递归方法 private void LoadData ( string paths , TreeNodeCollection nodes ) //跟目录路径和控件根节点 { string [ ] dnames = Directory . GetDirectories ( paths ) ; //获取当前目录下的所有子目录(路径和名称) foreach ( var item in dnames ) { //添加根节点 TreeNode IndexNode = nodes . Add ( Path . GetFileName ( item ) ) ; LoadData ( item , IndexNode . Nodes ) ; //递归调用 } /

递归算法

只愿长相守 提交于 2020-02-12 15:35:40
递归(recursion):程序调用自身的编程技巧。 递归满足2个条件: 1)有反复执行的过程(调用自身) 2)有跳出反复执行过程的条件(递归出口) 递归例子: (1)阶乘 n! = n * (n-1) * (n-2) * ...* 1(n>0) //阶乘 int recursive(int i) { int sum = 0; if (0 == i) return (1); else sum = i * recursive(i-1); return sum; } (2)河内塔问题 //河内塔 void hanoi(int n,int p1,int p2,int p3) { if(1==n) cout<<“盘子从”<<p1<<“移到”<<p3<<endl; else { hanoi(n-1,p1,p3,p2); cout<<“盘子从”<<p1<<“移到”<<p3<<endl; hanoi(n-1,p2,p1,p3); } } (3)全排列 从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。 如1,2,3三个元素的全排列为: 1,2,3 1,3,2 2,1,3 2,3,1 3,1,2 3,2,1 //全排列 inline void Swap(int &a,int &b) { int temp=a