递归:参见“递归”
(递归的定义:如题)
总体分析:
递归算法的效率是极低的(众所周知,函数调用是要耗费较多计算机资源的,而递归也是一种函数调用)。很多情况下,递归耗费的时间和占用的存储空间都要比非递归算法多。从我做的题目来说,递归规模稍微大点儿就已经TLE或爆栈了,如果你用过递归的方法求Fibbonacci Number你就知晓,当规模仅仅是50就暴慢啦,看着输出控制台憋了半天硬是没有把计算结果给憋出来啊,而非递归对此表示毫无压力。递归利用了堆栈段,由此就延伸出一雷区——递归里面开了大数组。要知道,局部变量都是放在堆栈段里的,递归里面开大数组会大大增加程序灭亡的风险。这里其实就牵涉到一个原则,大数组应该放在main函数外,也就是设置成全局变量,会更惬意。绝大多数的递归算法都可以转换为非递归的方式,当追求高效率时,不妨将递归算法稍微改改,自己去构造一个栈区,就可以改成非递归了。
有这样一个递归函数:
f(n){
...;
f(n-1);
f(n-2);
...;
}
以前自己研究递归代码或写递归算法时容易陷入一个思维定势:每次在主递归函数内部遇到被调用函数的时候,思维总是先一层层深入(比如遇到f(n-1),就会先在脑海中把它递归一遍),递归想通后再回到主递归函数(进行到f(n-2)),然后再继续……这样“有时候”是可以将这个算法理解的,但是最后会发现脑子乱成一团麻,这样就悲剧啦,递归算法就是让思路更清晰的啊。
后来,上面这个函数变成这样读的:从f(n)进来,然后遇到f(n-1),已经了解了f(n-1)有什么一个功能,然后直接读到f(n-2)……这种想法是先总体,再细致。为什么要先总体?因为每一层递归调用函数都是完整的,如果思维是先细致再总体,很容易掉进深渊找不着北,呼吁尊重函数的完整性有木有啊!
有一次,自己写出如下形式代码,现在看都一身汗啊:
f(int n){
int i;
for(i=0;i<n;i++){
f(i);
}
}
发现递归里面循环递归绝对杀伤脑细胞。如果想用上面循环递归的形式,不妨多想想是否可以是像Fibbonacci那样两项递归会更怡人。
一类常见问题:
1)直线切分平面
问题描述:n条直线,最多可以把平面分为多少个区域?

析:可能你以前就见过这题目,这充其量是一道初中的思考题。但这一个类型的题目还是从简单的入手,才容易发现规律。当有n-1条直线时,平面最多被分成了f(n-1)个区域。则第n条直线要是切成的区域数最多,就必须与每条直线相交且不能有同一交点。这样就会得到n-1个交点。这些交点将第n条直线分为2条射线和n-2条线断。而每条射线和线断将以有的区域一分为二。这样就多出了2+(n-2)个区域。
故:
f(n) = f(n-1) + n
写成对n的函数:
f(n) = f(n-1)+n
= f(n-2)+(n-1)+n
…
=2+2+…+n
=n(n+1)/2+1
2)折线分平面
问题描述:n条折线,最多可以把平面分为多少个区域?

析:根据直线分平面可知,由交点决定了射线和线段的条数,进而决定了新增的区域数。当n-1条折线时,区域数为f(n-1)。为了使增加的区域最多,则折线的两边的线段要和n-1条折线的边,即2*(n-1)条线段相交。那么新增的线段数为
4*(n-1),射线数为2。但要注意的是,折线本身相邻的两线段只能增加一个区域。
故:
f(n)=f(n-1)+4(n-1)+2-1
写成对n的函数:
=f(n-1)+4(n-1)+1
=f(n-2)+4(n-2)+4(n-1)+2
…
=f(1)+4+4*2+…+4(n-1)+(n-1)
=2n^2-n+1
3)封闭曲线分平面问题
问题描述:设有n个圆画在平面上,而任何两个恰好相交于两点,且任何三个圆不相交于同一点,问这些封闭曲线把平面分割成的区域个数。

析:当n-1个圆时,区域数为f(n-1).那么第n个圆就必须与前n-1个圆相交,则第n个圆被分为2(n-1)段线段,增加了2(n-1)个区域。
故:
f(n)=f(n-1)+2(n-1)
对n的函数为:f(n)=n^2-n+2
4)三角形切分平面
问题描述:用N个三角形最多可以把平面分成几个区域?

析:这题和直线切割平面的问题类似,当放第n个三角形的时候,这第n个三角形的每条边都和前n-1个三角形的一个尖角相交则这条边上产生2*(n-1)个交点,那么这个三角形一共有3*2*(n-1)个交点(我们知道,多出多少条线段,平面就被多分割出多少个部分)也就推出整个三角形被分割成3*2*(n-1)个部分(顶点不算交点),每个部分可以看成是一条线段,那么整个平面就多出了 3*2*(n-1) 个部分,完成
有:
f(1)=2
f(n)=f(n-1)+3*2*(n-1)
转换为:f(n)=2+3*n*(n-1)
从上面四种情况可以看出,假设我们已经知道规模为1或2的情况,并且知道了规模为n-1的情况,当规模加1达到n时会引起什么额外的变化,是关键要考虑的,也就是如上述例子所说会增加多少个交点、增加多少调公共边,这个变化我们设为x,那么就很容易得到:
f(n)=f(n-1)+x
上面的分析方法实际称作“递推”,这是一种从最基础、能目测的情况出发,推出规模为n时事件的结果的方法。递推和递归有很多相似之处,也许没有必要刻意把界限划分清楚。
递推可以看作是递归的反向。利用现有信息得到新信息,是递推的精髓。 ——摘自佳爷的黑书
递推引发的思考
递推的定义不难理解,困难就在如何从已知信息逐步推出后续信息。比如Fibonacci number(请允许我再次调用这万众皆知的家伙),我们看大兔生小兔的过程,1个兔,2个兔,3个兔,5个兔……生着生着规律就被Fibonacci总结出了,结果是喜人的,但过程是残酷的。
从已知信息得出规律才是递归的真正核心,一旦了解了规律,推出了公式,问题就迎刃而解了。很多事情说易做难,规律题往往让人痛不欲生啊有木有,如果想很快发现规律,自身各方面知识必须足够强大啊,各种组合数学、图论、数论、概率论,各种公式定理必须齐上阵啊,最蛋疼的有时候物理化学也来凑热闹啊有木有!
最后,我觉得,递推只是一种思考方式,而它本身是没有统一的公式的,每一道递推题都可以包含不同的规律。但是递推题也是最有意思的,能用一种很简单的规律或一条很简洁的公式去解决复杂的问题,自豪感必须倍增啊!!!
补数学去~~~

- 大小: 2.1 KB

- 大小: 2.1 KB

- 大小: 19.3 KB

- 大小: 2.9 KB
分享到:
相关推荐
合并排序算法、快速排序算法和递归分治是计算机科学中的基础概念,它们在数据处理和算法设计中占据着重要地位。以下是对这些知识点的详细解释: **合并排序算法(Merge Sort)** 合并排序是一种基于分治策略的排序...
提示:计时方法请参见参考书或课件。 2.统计给定的一组文本文件的英文单词、字符、数字字符、空白字符、英文字母和其他字符的个数请你扮演项目组程序员角色,认真阅读CodeForLab6.cpp和CodeForLab6.h中的开发要求,...
有关更多信息,请参见init_results.pdf的初始结果。 梯度下降方法基于Song等人(2016)发表的论文《训练用于认知任务的兴奋性-抑制性递归神经网络:简单灵活的框架》。 等 我们已经对与杨(Yang)等人在论文“训练...
Gerard - 优雅的递归 ReadDir Node.js 的递归 readdir 使用访问文件系统。 支持用于选择性列表的通配符。 安装 $ npm install gerard 用法 var gerard = require ( 'gerard' ) ; gerard ( path , [ options ] , ...
Javascript中的通用极简零依赖项递归下降解析器生成器。 您可以使用EBNF方式直接使用Javascript定义语法:请参见示例。 解析器根据指定的语法生成AST。 要见证此工具的强大功能,请查看:用Javascript定义并由...
参见_.camelCase() 和 。 import humps from 'lodash-humps' const object = { attr_one : 'foo' , attr_two : 'bar' , attr_three : { attr_one : 'foo' } } humps ( object ) // { attrOne: 'foo', attrTwo: '...
它是 NCHOOSEK 命令的递归替代方案,速度极快 (O(1)),代价是用户交互稍微多一些。 (你确实得到了 NCHOOSEK 没有给你的东西这个额外的努力:参见输入“m”。)除了它的效率之外,它很棒,因为每个新的 K 子集与...
利用二叉树法,实现汉诺塔的非递归,根据盘子数和第几步,快速得到每一步移动的操作,速度快,省内存。已经经过调试运行,算法思想参见http://wenku.baidu.com/view/81a05a80e53a580216fcfeba.html,本人源码是根据...
这个小辅助函数允许获取 ... 有关更详细的对象分析,请检出UIInspect(#17935)程序,有关Java类检查,请参见checkClass(#26947)。 但是,如果您想要一个轻量级的递归字符串表示,这个工具可能只是一个不错的选择。
使用递归: git clone --recursive https://github.com/javorszky/chassis-openssl.git可以获取子模块。 运行vagrant reload --provision或只是vagrant up 在机箱根目录中创建或编辑local-config.php并添加/编辑...
recursive-nystrom:Nyström方法的递归重要性采样 MATLAB代码实现了递归岭杠杆评分采样算法,该算法在(NIPS 2017)中开发。 安装 下载recursiveNystrom.m ,或直接将其包含在项目目录中。 有关用法的示例,请参见...
ssl_redirector ... 用法 在 JBoss Wildfly 上,更改 jboss-web.xml 中的主机名。 在其他服务器上,根据需要进行配置和安装。 历史 我的具体用例:临时支持使用 haproxy ... 递归:n,参见递归。 错误 可能有更好的方法。
使用随机类型的递归现实图生成器 这是什么代码? 该代码可用于生成随机图,这些图服从一堆可以在实际图中观察到的属性。 这些属性是: 图形是如何生成的? 一般的想法是通过随意在键盘(基本字符集)上键入来创建...
该模型计算每个先前处理步骤的递归加权平均值(RWA)。 通过这种方法,模型可以在序列中的任何地方形成直接连接。 这与仅使用先前处理步骤的传统RNN体系结构形成了鲜明对比。 RWA模型的详细说明已发布在的手稿中。 ...
递归查找给定属性的对象并获取其值。 安装 npm i get-last-value --save 用法 有关更多用例,请参见 var getLastValue = require ( 'get-last-value' ) getLastValue ( { foo : 'bar' , baz : 'qux' } , 'foo' ) //...
递归可视化器 递归可视化工具... += os.pathsep + 'C:/Program Files (x86)/Graphviz2.38/bin/' 的Ubuntu 安装graphviz sudo apt install graphviz 有关在其他操作系统上安装graphviz的说明,请参见 2.安装递归可视化器
有关库功能的详细说明,请参见。 安装 Pkg . Registry . add ( RegistrySpec (url = " https://github.com/dfcorbin/DCorbinJLReg " )) Pkg . add ( " RecursivePartition " ) 递归分区 假设我们有一个二维坐标数据...
递归下降到疯狂疯狂是一种Swift µframework,用于解析简单的无上下文语法中的字符串。 组合来自简单Swift表达式的解析器并进行解析: let digit = % ( " 0 " ... " 9 " ) <|> % ( " a " ... " f " ) <|> % ( ...
注意:如果您正在寻找V2客户端,请参见。 HTTP API的文档和示例代码可找到。入门正在安装该程序包以的名称发布在Packagist上,并且可以作为依赖项添加到项目的composer.json文件中。 我们建议使用来安装和维护此...
有关用法示例,请参见example.py。 当前实现的有: 简单的单隐层递归网络。 本质上是前馈网络,其中单个隐藏层的输出连接到其输入。 发条RNN。 描述的RNN的实现,其中只能连接具有相邻时钟速率的块。 在引用的出版...