递归算法

递归算法详细讲解

岁酱吖の 提交于 2019-12-12 13:39:58
原作者:书呆子Rico 《递归的内涵与经典应用》 http://my.csdn.net/justloveyou_ 摘要:   大师 L. Peter Deutsch 说过:To Iterate is Human, to Recurse, Divine.中文译为:人理解迭代,神理解递归。毋庸置疑地,递归确实是一个奇妙的思维方式。对一些简单的递归问题,我们总是惊叹于递归描述问题的能力和编写代码的简洁,但要想真正领悟递归的精髓、灵活地运用递归思想来解决问题却并不是一件容易的事情。本文剖析了递归的思想内涵,分析了递归与循环的联系与区别,给出了递归的应用场景和一些典型应用,并利用递归和非递归的方式解决了包括阶乘、斐波那契数列、汉诺塔、杨辉三角的存取、字符串回文判断、字符串全排列、二分查找、树的深度求解在内的八个经典问题。 一. 引子    大师 L. Peter Deutsch 说过:To Iterate is Human, to Recurse, Divine.中文译为:人理解迭代,神理解递归。毋庸置疑地,递归确实是一个奇妙的思维方式。对一些简单的递归问题,我们总是惊叹于递归描述问题的能力和编写代码的简洁,但要想真正领悟递归的精髓、灵活地运用递归思想来解决问题却并不是一件容易的事情。在正式介绍递归之前,我们首先引用知乎用户李继刚( https://www.zhihu.com

算法学习之分治、迭代、递归

五迷三道 提交于 2019-12-11 17:57:26
分治策略:将一个大的问题,分解为相对独立的小问题,通过解决这些小问题得到的答案来拼凑出最后的解。 迭代:从小规模的问题,逐步累积出较大问题的解,最终获得所需要解决问题的解 递归:通过不断调用自身,但是相对的每次调用自己时候,所解决的问题规模较小,比较符合分治的思想。 来源: CSDN 作者: qq_24605545 链接: https://blog.csdn.net/qq_24605545/article/details/103484742

排序算法系列——快速排序

旧街凉风 提交于 2019-12-11 14:00:51
什么是快速排序? 快速排序 ,顾名思义它排序的速度十分的快。 它快到什么程度呢? C语言标准库中的 qsort 函数就是使用快速排序实现的! 说到快速排序,离不开两个重要的概念: 递归 和 分治算法(Divide ans conquer, D&C) 。 如果要讲清楚这两个概念,可以单独写两篇文章出来了。 因此这里不做深入,只简单介绍一下: 递归 :重复调用自己的函数。一般由两个部分组成 基线条件 和 递归条件 ,程序在符合 基线条件 的时候返回,在符合 递归条件 的时候调用自己。 分治算法(Divide ans conquer, D&C) : 将大的问题化解为相同类型的小问题。一种著名的递归式问题解决办法,一般分为两个步骤,首先找出尽可能简单的 基线条件 ,然后将 递归 的将问题分解为小问题,直到小问题符合 基线条件 。 假如还不太明白这两个概念,没关系,看下面的例子就可以了。 排序过程 既然 快速排序 的核心思想是 D&C ,那么它的 基线条件 和 递归 条件分别是什么呢? 首先我们思考一下, 什么样的数组需要排序 ? 长度为 0 的数组需要排序吗? 不需要。因为它的没有顺序的概念。 长度为 1 的数组需要排序吗? 不需要。因为可以把它看做一个有序数组了。 长度为 2 的数组需要排序吗? 需要。因为并不能确定它的顺序。 因此,我们可以把 长度为0或1的数组 设为是 基线条件 。

在次线性时间内计算线性递归数列

最后都变了- 提交于 2019-12-11 00:07:48
date: 2019-09-13 简介 标题看着很高端,其实就是在 \(O(\log_2 N)\) 内计算出线性递归数列的某一项 (好像什么都没有解释清楚啊) 。 斐波那契数列的快速计算 我们先来看一个题目: 题目描述: ​ 给你一个数字 \(n\) ,你需要输出斐波那契数列的第n项。 ​ 注意: 第一项和第二项都为 \(1\) 。 题目输入: ​ 第一行一个整数 \(n\) ,保证$1 \leq n \leq 1e18 $。 题目输出: ​ 输出斐波那契数列的第n项,对 \(1e9+7\) 取模。 这道题目小数据范围内很简单 (一道水题) ,但是当数据范围扩展到 \(1 \leq n \leq 1e18\) 时,一切都不一样了。你需要一个 \(O(N \log_2 N)\) 的算法来解决它。这里我们需要用到矩阵运算。 递推式 斐波那契数列的递推式这个大家应该都会写吧。。。 算了我还是来写一下好了: \[ f_{i}=f_{i-1}+f_{i-2}\\ f_{0}=1\\ f_{1}=1 \] 转化为矩阵计算 这里我们把计算 \(f_0\) 和 \(f_1\) 包含在一个2行1列的矩阵中: \[ \begin{pmatrix} f_{0}\\ f_{1} \end{pmatrix} \] 之后我们可以得出如下的式子: \[ \begin{pmatrix} 0&1\\ 1&1

算法导论 第7章 课后习题

早过忘川 提交于 2019-12-10 04:30:48
7.2-4 银行经常按照交易时间,来记录有关某一账户的交易情况,但是,很多人喜欢按照票据号来收到其银行对账单。因此,如何将按交易时间排序转换成按支票编号来排序,就成为一个对几乎排好序的输入进行排序的问题。证明在这个问题上,过程INSERT-SORT的性能往往优于过程QUIKSORT。 问题解析: 对于QUIKSORT来说,输入一个已排序的数组属于最坏的情况,则每次区间划分都是最大程度的不对称。其算法运行的递归时间为T(n) = T(n-1) + Θ(n), 算法时间复杂度为Θ(n^2); 而对INSERT-SORT来说,输入一个已排序的数组却属于最佳的情况,算法时间复杂度为O(n)。也就是说当输入一个几乎排好序的数组,快速排序趋于最坏的情况,而插入排序却趋于最佳的情况。为降低这种最坏情况出现的概率,采用快速排序随机化版本,期望的运行时间为O(nlgn)。 7.3-2 在过程RANDOMIZED-QUIKSORT的运行过程中,最坏情况下对随机排序产生器RANDOM调用了多少次?最佳情况下调用了多少次?以Θ记号形式个给出你的答案。 问题分析: 随机快速排序中,只要区间包含元素数目大于1,则需调用RANDOMIZED-PARTITION,选取主元(pivot)进行区间划分, 而主元的选取需调用Random。主元(pivot)一旦被选出来后,就不会在加入到后续的排序了。直白来说就是

递归

只谈情不闲聊 提交于 2019-12-10 03:22:36
递归应用场景 看个实际应用场景,迷宫问题(回溯),递归(Recursion) 递归的概念 简单的说:递归就是方法自己调用自己,每次调用时传入不同的变量。递归有助于编程者解决复杂问题,同时可以让代码变得简洁。 递归的调用机制 1. 打印问题 /** * 打印问题 * @param n */ public static void test ( int n ) { if ( n > 2 ) { test ( n - 1 ) ; } System . out . println ( "n=" + n ) ; } 测试 public static void main ( String [ ] args ) { //通过打印问题,回顾递归调用机制 test ( 4 ) ; 2. 阶乘问题 /** * 阶乘问题 */ public static int factoriial ( int n ) { if ( n = = 1 ) { return 1 ; } else { return factoriial ( n - 1 ) * n ; } } 测试 public static void main ( String [ ] args ) { //通过打印问题,回顾递归调用机制 //test(4); //通过阶乘问题,回顾递归调用机制 int res = factoriial ( 2 ) ;

递归算法Recursion

亡梦爱人 提交于 2019-12-10 01:59:23
递归是一种常见的解决问题的方法,即把问题逐渐简单化。基本思想就是自己调用自己。 一个使用递归技术的方法将会直接或者间接的调用自己 void test01(){   test01();//自己调用自己就是递归   } void test02(){} test01死循环,要确定什么时候停止调用 -定义递归头。 什么时候调用自己 -递归体 public class Test { static long factorial(int n){ if (n==1) { return 1; }else{ return n*factorial(n-1); } } public static void main(String []args){ System.out.println(factorial(5)); } } 来源: https://www.cnblogs.com/iyon/p/3186462.html

算法 递归

情到浓时终转凉″ 提交于 2019-12-09 19:39:02
算法 递归 一、基础知识 1、迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值 2、描述迭代的一种方法是使用显式循环,如while和for循环。另一种完全不同的迭代实现方式是递归 3、递归是一种技术,这种技术是指通过函数在执行过程中一次或者多次调用其本身,或者通过一种数据结构在其表示中依赖于相同类型的结构更小的实例。 4、递归算法效率可能没有循环高,但是可读性和代码简洁性更强! 5、函数执行导致嵌套函数的调用时, 参数、局部变量和执行位置信息压栈 ,调用结束后恢复。递归调用也是这样的过程。当函数的依次调用需要进行递归调用时,该调用被挂起,直到递归调用完成。 6、在python中,当一个函数被调用时,为此创建一个 活动记录或框架 的结构来存储信息。活动记录里面存储函数调用的参数和局部变量的命名空间。 函数调用自身时,也是两个不同的函数(不同命名空间)在交流。 7、如果一个函数的执行导致嵌套函数的调用(其他函数或者函数调用自身),前者的调用将被挂起,其 活动记录将存储源代码中的位置(源代码中调用函数代码的下一条指令的存储位置) ,这个位置是 调用函数返回后 将继续执行的 控制流 。return之后根据 活动记录(栈)中的参数、局部变量和源代码下一条指令的位置 ,执行对应的指令操作。 8

用C++编写简单绘图语言的语法分析器

喜夏-厌秋 提交于 2019-12-09 13:03:13
语法分析器 概述 从词法分析的角度看,语言是一个单词的集合,称之为正规集,单词是由一个个字符组成的线性结构;从语法分析的角度看,语言是一个句子的集合,而句子是由词法分析器返回的记号组成的非线性结构。反映句子结构的最好方法是树,常用的有分析树和语法树。分析语法结构的基本方法有两种: 自上而下 分析方法和 自下而上 分析方法。自上而下分析从根到叶子建立分析树,而自下而上分析恰好相反。在这两种情况下,分析器都是从左到右地扫描输入,每次读进一个记号。 与词法分析类似,语法分析也具有双重含义: ①规定句子形成的规则,也被称为语法规则。程序设计语言的大部分语法规则可以用上下文无关文法( Context Free Grammar , 简称 CFG )来描述。 ②根据语法规则识别记号流中的评议结构,也被称为语法分析。最有效的自上而下和自下而上的分析方法都只能处理上下文无关文法的子类,如 LL 文法和 LR 方法,但是它们已足以应付程序设计评议的绝大多数语法现象。 一、任务与目的 ·上机任务: 1 、使用 C/C++ 程序设计语言和递归下降子程序的方法编写该函数绘图语言的词法分析器。并要求设计一个语法分析器的测试小程序来调用自己编写的语法分析器测试各种不同的输入。 2 、语法分析的任务是在词法分析基础上,根据语言的语法规则,把词法符号分解成各类语法单位。语法分析所依据的是语言的语法规则

Python 实现递归算法之汉诺塔

时间秒杀一切 提交于 2019-12-08 11:36:42
如图的小游戏,汉诺塔: 游戏的目的是将最左边的三块移动到最右边,游戏即为成功。 下面按照代码的步骤进行移动,三根柱子分别代表了x,y,z: 发现可以实现游戏目的! 当然,三个对于很多人来说并不难实现目标,但是当块变成了5个甚至8个呢 下面,我们来试试7个方块,同样是三根柱子,人的计算就很难实现游戏目标了 所以我们用代码来试试: 可以看到非常长,所以我来按照他的指示来进行游戏 游戏成功! 总共有128步操作,如果人为的来进行游戏的话,很有可能会出错。 所以在此运用了递归算法,编写递归函数来教我们如何进行下一步。 以下是汉诺塔的源代码: def hanoi(n ,x ,y ,z): if n == 1: print(x, '-->' ,z) else: hanoi(n-1,x,z,y) print(x ,'-->' ,z) hanoi(n-1,y,x,z) n = int(input("请输入层数:")) hanoi(n,'x','y','z') 来源: https://www.cnblogs.com/lesliechan/p/12005059.html