递归算法

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 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、注意事项 使用方法 使用递归的时候,要明确业务逻辑可以分解为重复相同的问题

java递归和反向递归

淺唱寂寞╮ 提交于 2020-01-01 15:56:05
1. 递归查询树tree结构有两种做法 : 第一种,递归查询数据库结构, 第二种,一次性将数据库表中的所有数据查出来,然后再递归查出来的list集合, 第一种做法适合数据量较少的tree结构,因为要一直查询数据库数据量大时速度回相对较慢,所以数据量大时建议使用第二种方法,如 图1 所示是一个常见的树tree结构 图1 2. 反向递归(逆向递归)查询树tree结构根据关键字过滤数据 大家有么有遇到过这个问题:我想要根据关键字过滤查询出相关数据和它的上级结构,得到 图1所示 结果,可往往不知道怎么做,查不出上级结构总是得到 图3 类似的结构,要解决这个比较常见的问题就要用到反向递归的算法,网上我那个网搜不到类似的解决方案,本人一时兴趣来了,做了一套递归和反递归的解决方案,简单易懂,大家可以相互交流一下 图2 图3 3.示例代码 [java] view plain copy /** * 说明方法描述:将list转为树tree结构 * * @param allRrecords * @return * @time 2016年5月10日 下午6:00:35 * @author yangdong */ public List<Record> useListRecordToTree(List<Record> allRrecords) { List<Record> listParentRecord

字典序全排列算法研究

|▌冷眼眸甩不掉的悲伤 提交于 2020-01-01 01:36:07
  最近对数学方面很有兴趣,周末和同学去大学蹭课,其中在讲排列组合的时候讲到了全排列的字典序生成算法,我觉得这个想法真的挺好,去网上找了找,貌似都是递归求全排列,没有讲到这个算法的,今天我将这个算法写出来了,发在这里,以后学习。    非递归方法(字典序法):   这种算法被用在了C++的STL库中。   对给定的字符集中的字符规定了一个先后关系,在此基础上规定两个全排列的先后是从左到右逐个比较对应的字符的先后。  [例]字符集{1,2,3},较小的数字较先,这样按字典序生成的全排列是:     123,132,213,231,312,321   ※ 一个全排列可看做一个字符串,字符串可有 前缀 、 后缀 。   生成给定全排列的下一个排列.所谓 一个的 下一个 就是这一个与下一个之间 没有其他的 。这就要求这一个与下一个有尽可能 长 的 共同前 缀 ,也即变化限制在尽可能 短 的 后缀 上。 [例]839647521是1--9的排列。1—9的排列最前面的是123456789,最后面的987654321,从右向左扫描若都是增的,就到了987654321,也就没有下一个了。否则找出第一次出现下降的位置。 【例】 一般而言,设P是[1,n]的一个全排列。       P=P1P2…Pn=P1P2…Pj-1PjPj+1…Pk-1PkPk+1…Pn     find:  j=max{i

Problem D: 深入浅出学算法013-摆动数列

百般思念 提交于 2019-12-30 12:28:25
Problem D: 深入浅出学算法013-摆动数列 Time Limit: 1 Sec Memory Limit: 64 MB Submit: 3535 Solved: 1424 Description 已知递推数列 a(1)=1,a(2i)=a(i)+1,a(2i+1)=a(i)+a(i+1),i为正整数,求该数列的第n项,前n项中的最大值 Input 多组测试数据,首先输入T表示组数,然后每行输入整数n(n<=3000) Output 对于每个n输出一行,每行2个整数分别是第n项的值以及前n项的最大值 Sample Input 1 2011 Sample Output 225 321 HINT 其实这道题就是个递归。有些同学是用函数递归,这里我想说的是,函数递归在数字大的时候容易TLE,所以把函数递归改成数组,就可以节省很大的时间。 至于这题的递归,讲白了就是分奇偶的情况进行递归就行了。 上代码: #include<stdio.h> #include<string.h> int a[10000]; int main(void) { int t,n,i,k,p; while(scanf("%d",&n)!=EOF) { for(i=0;i<n;i++) { memset(a,0,sizeof(a)); scanf("%d",&t); a[0]=0;a[1]=1;a[2]=2;a

数据结构与算法之递归

一世执手 提交于 2019-12-28 19:43:39
递归: 定义:一个函数自己直接或间接调用自己 (不要写成死递归) 举例: 1. 1+2+3+4+...+100的和 求阶乘 汉诺塔 走迷宫 函数的调用(以 C语言为例) 当一个函数的运行期间调用另一个函数时,在运行被调用函数之前,系统需要完成三件事: 将所有的实际参数,返回地址(即调用函数的位置,等到调用函数执行完毕后返回这个位置,继续执行下面的代码)等信息传递给被调函数保存 为被调函数的局部变量(也包括形参)分配存储空间 将控制转移到被调函数的入口 从被调函数返回主调函数之前,系统也要完成三件事: 保存被调函数的返回结果 释放被调函数所占的空间(指静态空间,不包括 malloc动态分配的空间) 依照被调函数保存的返回地址将控制转移到调用函数 当有多个函数相互调用时,按照 “后调用先返回”的原则,上述函数之间信息传递和控制转移必须借助“栈”来实现,即系统将整个程序运行时所需的数据空间安排在一个栈中,每当调用一个函数时,就在栈顶分配一个存储区,进行压栈操作,每当一个函数退出时,就释放它的存储区,就进行出栈操作,当前运行的函数永远都在栈顶位置。 递归必须满足的条件 递归必须得有一个明确的终止条件 该函数所处理的数据规模必须在递减 这个转化必须是可解的 循环和递归 递归 易于理解 速度慢 存储空间大 循环 不以理解 速度快 存储空间小 汉诺塔伪算法 if(n > 1) { 先把