递归调用

Fibonacci数列一般方法以及递归调用

匿名 (未验证) 提交于 2019-12-03 00:19:01
一般算法 一般方法 package edu.xatu; import java.util.Scanner ; public class Fibonaci { public static void main(String[] args ) { //求斐波那契 int [] a = new int [10]; for ( int i =0; i < a . length ; i ++) { if ( i <=1) { a [ i ] = 1; } else { a [ i ] = a [ i -1] + a [ i -2]; } } for ( int i =0; i < a . length ; i ++) { System. out .print( a [ i ]+ " " ); } } } 运行结果: 递归调用方法 import java.util.Scanner; public class Fibonacci { //递归调用,n为第n个数 public static int fabonacci( int n ) { if ( n <=1) return 1; return fabonacci ( n -1)+ fabonacci ( n -2); } public static void main(String[] args ) { Scanner s = new

递归算法讲解

匿名 (未验证) 提交于 2019-12-03 00:19:01
一. 引子    大师 L. Peter Deutsch 说过:To Iterate is Human, to Recurse, Divine.中文译为:人理解迭代,神理解递归。毋庸置疑地,递归确实是一个奇妙的思维方式。对一些简单的递归问题,我们总是惊叹于递归描述问题的能力和编写代码的简洁,但要想真正领悟递归的精髓、灵活地运用递归思想来解决问题却并不是一件容易的事情。在正式介绍递归之前,我们首先引用知乎用户李继刚( https://www.zhihu.com/question/20507130/answer/15551917 )对递归和循环的生动解释:    递归:你打开面前这扇门,看到屋里面还有一扇门。你走过去,发现手中的钥匙还可以打开它,你推开门,发现里面还有一扇门,你继续打开它。若干次之后,你打开面前的门后,发现只有一间屋子,没有门了。然后,你开始原路返回,每走回一间屋子,你数一次,走到入口的时候,你可以回答出你到底用这你把钥匙打开了几扇门。    循环:你打开面前这扇门,看到屋里面还有一扇门。你走过去,发现手中的钥匙还可以打开它,你推开门,发现里面还有一扇门(若前面两扇门都一样,那么这扇门和前两扇门也一样;如果第二扇门比第一扇门小,那么这扇门也比第二扇门小,你继续打开这扇门,一直这样继续下去直到打开所有的门。但是,入口处的人始终等不到你回去告诉他答案。   

算法第二章作业

匿名 (未验证) 提交于 2019-12-03 00:13:02
在这一年的打题过程中,从最开始的手敲冒泡排序到现在一直用STL里的sort,排序算法使用的频率可以说是非常高的了,而且各种排序算法的思想和有关的一些数据结构也会经常用到,但之前一直听说sort是基于快排的,就会有疑问――堆排序的最坏最好复杂度都是nlogn,而快排的最坏复杂度是n 2 ,为什么不用堆排呢。国庆这几天断断续续地看完了老师给的博客之后终于明白了这个问题,而且更加深入地了解了sort函数对快排的极致优化。 从平均时间上来说,堆排的时间常数要比快排大,因为堆排会让某些数据出现很多大幅度的无效的移动,而快排则是将每个元素快速地移动到最终位置上或是附近,然后进行小范围的移动,详见 https://www.zhihu.com/question/20842649 http://mindhacks.cn/2008/06/13/why-is-quicksort-so-quick/ 那么std::sort又是怎么实现来尽量避免快排的最坏情况呢,这篇博客给出了详细的解答 http://feihu.me/blog/2014/sgi-std-sort/ 为了让自己看的时候不至于被各种函数名弄晕,做了个图辅助一下 基于个人的理解 __introsort_loop这个函数的主体部分就是快速排序的部分,但它与一般的快排不一样的是,为了尽量减少枢轴为极值引起的递归恶化,它选取了开头、中间

C# 使用递归获取所有下属、所有子部门……

匿名 (未验证) 提交于 2019-12-03 00:11:01
本例中获取的是所有的晚辈!首先定义家庭成员类: public class FamilyMember { /// <summary> /// 身份 /// </summary> public string identity { get ; set ; } public int level { get ; set ; } /// <summary> /// 父亲 /// </summary> public string father { get ; set ; } } 然后,定义递归方法: /// <summary> /// 递归获取晚辈 /// </summary> /// <param name="members"></param> /// <param name="m"></param> /// <returns></returns> public static List < FamilyMember > GetYoungers ( List < FamilyMember > members , FamilyMember m ) { var result = new List < FamilyMember >(); //获取该员工的直属下级 var subordinate = members . Where ( e => e . father == m . identity ).

使用递归方法判断回文

匿名 (未验证) 提交于 2019-12-03 00:11:01
首先 分析问题,判断回文就是需要从判断第一个与最后一个是否一样,第二个和倒数第二个是否一样,第三个和倒数第三个........依次类推,可能的需要注意的情况有三种:奇数、偶数、就一个字符。 首先,先从简单的不使用递归的方式来写: //判断是否是回文 import java.util.Scanner; public class Testpalindrome { public static void main(String args[]) { System.out.println("请输入一段字符串:"); Scanner scanner=new Scanner(System.in); String str=scanner.nextLine(); int a=str.length();//判断字符串的长度 if(a%2==0) { for(int i=0;i<a;i++) { if(str.charAt(i)!=str.charAt(a-1-i)) { System.out.println("所输入的字符串不是回文"); break; } if(i==a/2) { System.out.println("所输入的字符串是回文"); break; } } } if(a%2==1) { for(int i=0;i<a;i++) { if(str.charAt(i)!=str.charAt

线程同步锁、死锁、递归锁、信号量、GIL

匿名 (未验证) 提交于 2019-12-03 00:09:02
Ŀ¼ 所有线程同一时间读写同一个数据,有的线程已经对数据进行修改了,造成有的线程拿到的数据时旧的数据,而不是修改后的数据,造成结果不正确,于是引入了同步锁解决问题, 同步锁的原理是同一时间只能有一个线程读写数据。 锁通常被用来实现对共享资源的同步访问。从threading模块导入一个Lock类,为每一个共享资源创建一个Lock对象,当你需要访问该资源时,调用acquire方法来获取锁对象(如果其他线程已经获得了该锁,则当前线程需等待其被释放),待资源访问完后,再调用release方法释放锁。 下面这个例子就需要用到同步锁: from threading import Thread x = 0 def task(): global x for i in range(20000): x=x+1 # t1 的 x刚拿到0 保存状态 就被切了 # t2 的 x拿到0 进行+1 1 # t1 又获得运行了 x = 0 +1 1 # 思考:一共加了几次1? 加了两次1 真实运算出来的数字本来应该+2 实际只+1 # 这就产生了数据安全问题. if __name__ == '__main__': t1 = Thread(target=task) t2 = Thread(target=task) t3 = Thread(target=task) t1.start() t2.start() t3

二叉树算法题

匿名 (未验证) 提交于 2019-12-03 00:05:01
二叉树层次遍历 //思路 特殊情况 ,根节点为null,深度为0,return 0 借助队列,队列储存每一层的所有节点, 先保存数组长度,用于控制依次遍历循环――遍历每一个节点保存值,该节点的所有子结点从队尾入队,访问过的节点从头出队 注意――需要先把width存下来,用于for循环的结束标志,因为for循环里面直接操作了queue,不能去都不敢动态获取 队列初始值为root,对每一层都要进行上述遍历――while循环控制,队列空代表叶节点这一层遍历完成,此时遍历结束,退出循环 每次循环开始前初始化一个curNodes储存该层所有节点,每次循环结束,将curNodes压入result var levelOrder = function(root) { if (root === null) return []; //空树 var result = [], queue = [root]; while (queue.length) { let width = queue.length; //需要先把width存下来,用于for循环,for循环里面直接操作了数组 let curNodes = []; for (let i = 0; i < width; i++) { let node = queue.shift(); curNodes.push(node.val); node.left ?

关于递归和动态规划的简单理解

匿名 (未验证) 提交于 2019-12-03 00:05:01
简单的来说,递归就是一个概念能够用自身来解释,比如说一本字典,每个字词的解释是依靠字典中其他的字词来解释的。一般来说,计算机中遇到的递归问题大多是把一个问题分解成规模更小的子问题求解,再进行合并。 一个具有递归性质的问题,大多具有两个特征,第一个是状态转移方程也就是递归方程,比如在求解阶乘时,n!=n*(n-1)!,就将求解n的阶乘转换为求解n-1的阶乘。第二个特征就是终止条件,一个递归是一类问题的求解,必定有一个结果 无法一只递归下去,有一个结束条件,也就是当问题规模简化的足够小的时候可以直接的出答案。在求解阶乘时,当问题过为1的时候就直接输出1. int f ( n ) { if ( n == 1 ) //终止条件 { return 1 ; } else { return n * f ( n - 1 ); //递归方程 } } 递归执行时,递归函数会被反复地调用,一层一层的进入,到达终止条件后,再一层一层出来,为了保证结果的正确性,每一层函数的运算结果和状态都必须保存在系统所分配的栈里面,当数据量很大的时候,递归所占用的空间和运行时间会非常恐怖,效率也很低 这里再介绍一种和递归类似的但执行效率更高的动态规划算法。 递归算法是从顶置低求解问题,而・动态规划算法是从低置顶求解问题,同样也需要状态转移方程方程,和初始条件,相较于递归算法的优势,动态规划算法不需要反复调用自身函数

递归原理

匿名 (未验证) 提交于 2019-12-03 00:04:02
递归思想 程序调用自身的编程技巧称为递归( recursion) 例如,设计一个程序设计计算n!。 先分析递归的思想,现在要计算6! 分解为6×5! 分解为6×5×4! 分解为6×5×4×3! ... 分解为6×5×4×3×2×1 #include <stdio.h> int fact ( int n ) { if ( n == 1 ) return 1 ; else return n * fact ( n - 1 ); } int main () { printf ( "%d" , fact ( 3 )); return 0 ; } 递归的程序是 int fact(3) { if(n==1) return 1; else return 3*fact(2); //这里的fact(2)又是一个递归程序 //因为不知道fact(2)的值所以只能继续调用fact(2) } int fact(2) { if(n==1) return 1; else return 2*fact(1); } int fact(1) { if(n==1) return 1; else return 1*fact(0); } 当程序运行到fact(1)时候,return 1,回调,所以fact(2) return 2*1,所以fact(3)return3*2*1。最后得到答案 来源:博客园 作者: 帅气的涛啊

递归与动态规划的异同

匿名 (未验证) 提交于 2019-12-03 00:04:02
递归和动态编程(Dynamic Programming, DP)是算法类问题中的难点所在。算法的核心在于找到状态转移方程,即如何通过子问题解决原问题。 相似 递归和动态编程能解决的问题都有一个特性:原问题(problem)可以分解成若干个子问题(sub-problem),只有先解决了子问题才能进一步解决原问题。子问题的解决方式形式上与原问题一致。 区别 DP和递归有什么不同?最大的区别在于,DP 存储子问题的结果 ,当子问题已经被计算过,直接返回结果。因此,当需要重复计算子问题时,DP的时间效率高很多,但 需要额外的空间 。 递归的时间成本随递归深度n(单条路径中递归调用的次数)成指数增长;空间复杂度为O(n)。 动态编程的核心在于,如果在一个问题的解决方案中,子问题被重复计算,那么就可以利用记录中间结果,达到用空间换取时间的目的。 什么是动态规划 来源:51CTO 作者: QilanAllen 链接:https://blog.csdn.net/QilanAllen/article/details/100805998