递归调用

php递归算法总结

天涯浪子 提交于 2020-01-07 03:21:03
递归算法的实现方法是有多种的,如通过“静态变量”、“全局变量”、“引用传参”的方式: 静态变量 的方法: <?php function call(){ static $i = 0; echo $i . ''; $i++; if($i<10){ call(); } } call(); 输出: 0 1 2 3 4 5 6 7 8 9 利用static定义静态变量来实现递归排序。如上我们定义了一个call方法和静态变量$i,如果我们不给$i变量添加判断,而是直接运行,就会出现死循环。所以我们这里添加了一个if条件判断语句。最后循环调用自身方法 全局变量Global 实现递归: 1 <?php 2 $i=1; 3 function call(){ 4 global $i; 5 echo $i; 6 $i++; 7 if($i<=10){ 8 call(); 9 } 10 } 11 call(); 输出: 12345678910 如果没有在方法体内用global 定义$i,则会出现$i未被声明的错误。并且需要注意,在函数体内定义的global变量,函数体内可以使用,在函数体外定义的global变量不能在函数体内使用。 注:Global的作用是定义全局变量,但是这个全局变量不是应用于整个网站,而是应用于当前页面,包括include或require的所有文件。递归即调用自身的函数。在使用递归时

递归和迭代的比较

自作多情 提交于 2020-01-06 14:33:15
递归和迭代----算法中的递归和迭代 递归 递归就是指程序调用自身的编程思想,即一个函数调用本身 递归的使用能把一个复杂的问题,转化为一个与原问题相似的规模较小的问题来解决,可以极大的减少编程中的代码量 迭代 迭代是利用已知的变量值,根据递推公式不断演进得到变量的一个新值的编程思想 二者比较 递归中一定有迭代,但是迭代中不一定有递归;大部分可以相互转换。 相对来说,能用迭代不用递归(因为递归不断调用函数,浪费空间,容易造成堆栈溢出) 迭代难以理解,但是其执行过程中效率高;递归则易于理解,但是其执行效率相对于迭代低 在设计中,从效率考虑,如果能用迭代的话,就用迭代;但是从程序算法的理解来看,递归更容易理解。 二者优缺点 递归 优点: 能用有限的循环语句来实现无限集合 递归实现的代码易于理解,利于其他人对代码的解读 能将大问题转化成小问题,减少编程中的代码量 缺点: 递归的过程中,会不断调用自身,会造成空间的浪费 调用次数过多后,容易造成堆栈溢出 迭代 优点: 迭代的算法执行效率高,运行花费的时间只随循环的增加而增加 迭代没有额外开销,不会有过多的内存消耗 缺点: 迭代实现的代码难以理解 代码的设计不如递归设计的代码简洁 编写复杂问题,比如图、表、二叉树……等的问题时,代码逻辑不易想出,实现较为困难 来源: CSDN 作者: 小白苏 链接: https://blog.csdn.net

链表练习题

我是研究僧i 提交于 2020-01-06 00:44:37
这段时间将会用这版面来记录一些链表的题目,脚踏实地去理解链表和使用链表。加油。(也许不是最优解,但是一定是符合题目要求的而且AC的) 1.移除链表元素 leetcode203题目:删除链表中等于给定值 val 的所有节点。 这是开始写的第一道,准备用3种方式来完成这道题目,记录自己的思路。 1.一般使用head节点完成 思路:既然是链表的删除元素,也只有next才能访问到其他元素,所以从head开始判断就好。 需要分别对head 和head.next进行判断. 其实就是遍历链表:时间复杂度O(N) public ListNode removeElements(ListNode head, int val) { //如果头节点的val就是要找的val, while(head!=null && head.val ==val ){ head = head.next; } //链表的val全是val if(head ==null){ return head; } //删除head.next位置 ListNode prev = head; while(prev.next!=null){ if(prev.next.val == val){ prev.next = prev.next.next; }else{ prev = prev.next; } } return head; } 2

基于递归算法,树形结构数据下业务场景,封装解决方法

南楼画角 提交于 2020-01-04 00:37:20
本文源码: GitHub·点这里 || GitEE·点这里 一、递归算法 1、概念简介 递归算法的核心思想是通过将问题重复分解为同类的或其子问题的方式,从而可以使用统一的解决方式。很多编程语言支持方法或函数自我调用,简单的说,就是在函数或方法体内,自身可以再次调用自身的方法结构。 2、基础案例 这里通过递归的方式,计算阶乘、求和等相关逻辑。 public class Demo01 { public static void main(String[] args) { int result1 = factorial(5); System.out.println(result1); int result2 = sum(100) ; System.out.println(result2); } // 递归阶乘 private static int factorial (int n){ if(n <= 1){ return n ; }else{ return n*factorial(n-1); } } // 递归求和 private static int sum (int f){ if(f <= 1){ return f ; }else{ return f + sum(f-1); } } } 3、注意事项 使用方法 使用递归的时候,要明确业务逻辑可以分解为重复相同的问题

算法导论笔记(一):复杂度,分治,随机

落爺英雄遲暮 提交于 2020-01-04 00:10:49
示例与概念 插入排序 归并排序 最坏情况分析与平均情况分析 函数增长的渐进记号 (O(n)) 表示函数增长的上界。即,花费时间不会高于线性增长。 (Theta(n)) 同时表示上界和下界。即,花费时间一定是这个线性增长的。 (Omega(n)) 表示增长的下界。 (o(n)) 表示不渐进紧确的上界。如, (2n =O(n^2)) , (n^2=O(n^2)) , (2n=O(n^2)) ,但 (n^2neq o(n^2)) (omega(n)) 与 (o(n)) 类似,表示不紧确的下界。 此外,常用 (T(n)) 表示所需的实际时间的函数。 分析分治算法,以归并排序为例 归并排序最坏运行时间的递归式: [ T(n)=begin{cases}Theta(1)&text{若} n=1,\ 2T(n/2)+Theta(n)&text{若} n>1. end{cases} ] 除使用主定理外,还可以这样理解递归式的值:将递归过程看做一个二叉树。递归调用中的每一层的总代价均为 (cn) ,其中 (c) 为常数。而二叉树的层数应为 (log_2n+1) 。故,整个算法的代价期望为 (Theta(nlog_2n)) 。 分治法 分治法求最大和的子数组 分解。将数组划分为两个子数组。此时,只存在三种子数组: 全部位于中点左侧的子数组 全部位于中点右侧的子数组 跨越中点的子数组 解决

深究递归和迭代的区别、优缺点及实例对比

不想你离开。 提交于 2020-01-03 22:42:03
1.迭代是人,递归是神! 从“编程之美”的角度看,可以借用一句非常经典的话: “迭代是人,递归是神!” 来从宏观上对二者进行把握。 从概念上讲,递归就是指程序调用自身的编程思想,即一个函数调用本身;迭代是利用已知的变量值,根据递推公式不断演进得到变量新值得编程思想。 2.递归 递归就是函数自己调用自己。 2.1构成递归需具备的条件: 子问题须与原始问题为同样的事,且更为简单; 2. 不能无限制地调用本身,须有个出口,化简为非递归状况处理。 2.2递归的基本原理 第一: 每一级的函数调用都有自己的变量。 第二: 每一次函数调用都会有一次返回。 第三: 递归函数中,位于递归调用前的语句和各级被调用函数具有相同的执行顺序。 第四: 递归函数中,位于递归调用后的语句的执行顺序和各个被调用函数的顺序相反。 第五: 虽然每一级递归都有自己的变量,但是函数代码并不会得到复制。 2.3递归优缺点 2.4编写一个递归函数 这个递归函数的功能是什么,怎样调用这个函数,即设计好递归函数的返回值和参数列表 什么时候应该结束这个递归,它的边界条件(出口)是什么(边界条件) 在非边界情况时,怎样从第n层转变成第n+1层(递推公式) 例: int f(int n) {   //出口 if (n > 0) { return n + f(n - 1); } else { return 0; } } 解析: 具体步骤

基于递归算法,树形结构数据下业务场景,封装解决方法

こ雲淡風輕ζ 提交于 2020-01-03 09:29:06
本文源码: GitHub·点这里 || GitEE·点这里 一、递归算法 1、概念简介 递归算法的核心思想是通过将问题重复分解为同类的或其子问题的方式,从而可以使用统一的解决方式。很多编程语言支持方法或函数自我调用,简单的说,就是在函数或方法体内,自身可以再次调用自身的方法结构。 2、基础案例 这里通过递归的方式,计算阶乘、求和等相关逻辑。 public class Demo01 { public static void main(String[] args) { int result1 = factorial(5); System.out.println(result1); int result2 = sum(100) ; System.out.println(result2); } // 递归阶乘 private static int factorial (int n){ if(n <= 1){ return n ; }else{ return n*factorial(n-1); } } // 递归求和 private static int sum (int f){ if(f <= 1){ return f ; }else{ return f + sum(f-1); } } } 3、注意事项 使用方法 使用递归的时候,要明确业务逻辑可以分解为重复相同的问题

快速排序和归并排序

走远了吗. 提交于 2020-01-03 05:24:41
1,快速排序 快速排序通过分割值列,然后递归的对两个部分进行排序,从而实现对值列的排序。它的基本思想是:通过一趟排序将要排序的 数据分割 成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序 首先任意选取一个数据(通常选用第一个数据)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序 。 怎么实现呢?--- 它的关键在于完成一趟快排后,基准元素在哪个位置,每次都选取一个分割列的第一个元素作为基准元素,来寻找用它来分割排序列后它自己所处的位置,编写一个 int findPartition(data,min,max)方法,用于 使用data[min]作为基准元素把data[min]到data[max]分割为两个部分,并返回分割以后基准元素自己所在的位置索引。 在主函数里这样来调用: public static void quickSort(Comparable[] data,int min,int max) { int mid; if(min < max) { mid = findPartition(data,min,max); quickSort(data,min,mid-1); quickSort(data,mid+1,max); } } 理解递归过程:::if(min <

Winter Vacation Training(1st Week)

让人想犯罪 __ 提交于 2020-01-03 04:02:06
7-1 子集和问题 (50分) 设集合S={x1,x2,…,xn}是一个正整数集合,c是一个正整数,子集和问题判定是否存在S的一个子集S1,使S1中的元素之和为c。试设计一个解子集和问题的回溯法。 输入格式: 输入数据第1行有2个正整数n和c,n表示S的大小,c是子集和的目标值。接下来的1行中,有n个正整数,表示集合S中的元素。 是子集和的目标值。接下来的1 行中,有n个正整数,表示集合S中的元素。 输出格式: 输出子集和问题的解,以空格分隔,最后一个输出的后面有空格。当问题无解时,输出“No Solution!”。 输入样例: 在这里给出一组输入。例如: 5 10 2 2 6 5 4 输出样例: 在这里给出相应的输出。例如: 2 2 6 思路: 一道老题就不多赘述了。主要说一下递归中如何强制跳出整个递归(详见代码)。 利用异常跳出整个递归。先写一个静态的StopMsgException类,再继承RuntimeException类,主函数调用递归部分直接而try,catch,注意catch里是StopMsgException e,最后递归里需要跳出的地方用throw StopMsgException抛出异常就ok了。 用return是无法跳出递归的,只会返回上一级!!! 怎么剪枝优化最后一个点都超时,比赛的时候给1s应该没问题,不必管他了。 dfs的else里的优化其实不用那么复杂

java递归调用 return的问题

淺唱寂寞╮ 提交于 2020-01-02 22:32:08
最近比较闲,写了个递归调用获取最大公约数,刚开始写错了,但一直不明白错在哪,错误代码如下: public class Demo { public static void main(String[] args) { int gcd = gcd(5, 15); System.out.println(gcd); } private static int gcd(int a, int b) { if (b != 0) { int i = a % b; a = b; b = i; gcd(a, b); } return a; } }   刚开始一直想不明白为什么当b!=0的时候 不直接return a的值 而是往gcd方法里走,直到a等于传入的值时才返回 后来就写了2个方法来debug 找到原因后 修改代码如下: public class Demo { public static void main(String[] args) { int gcd = gcd(4, 10); System.out.println(gcd); } private static int gcd(int a, int b) { if (b != 0) { int i = a % b; a = b; b = i; return gcd(a, b); } return a; } } 来源: https://www