递归算法

递归的理解

断了今生、忘了曾经 提交于 2019-11-28 19:44:01
递归算法概念是函数调用自己来实现的某种功能,按以下方法理解递归你会恍然大悟(如果你对递归有疑惑的话),并觉得递归是如此简单: 1.递归是高中数学中的数列那一章讲的内容。数列这章讲了一个概念叫递推公式:如果已知数列的第1项(或前几 项),且从第二项(或某一项)开始的任一An与它的前一项An-1(或前几项)间的关系可以用一个公式来表 示,那么这个公式就叫递推公式,递推公式是给出数列的一种方法。 2.例如斐波那契数列的递推公式就是:An=An-1+An-2(n>2,a1=1,a2=1) 3.那么现在如果想用递归的方式表示斐波那契数列即可定义函数f(n):当n>2时f(n)=f(n-1)+f(n-2);当n=1时f(n)=1,当n=2时f(n)=1; 即private static int fibonacciRe(int i) { if(i == 1 || i == 2) return 1; else if(i>2) return fibonacciRe(i-1)+fibonacciRe(i-2); else return 0; } 4.解释:其实说白了递归函数就是一个递推公式,只要递推公式往纸上一写,把项A替换成函数名字,把n替换成函的 参数即可,最后用if处理一下特殊参数值时的结果值就欧了。 5.总结:我们为什么有些人很难理解递归函数呢

迭代是人,递归是神(迭代与递归的总结:比较)

陌路散爱 提交于 2019-11-28 17:46:08
版权声明:本文为博主原创文章,转载请注明出处http://blog.csdn.net/lg1259156776/。 https://blog.csdn.net/LG1259156776/article/details/46849809 在计算机编程实现中有常常两种方法:一曰迭代(iterate);二曰递归(recursion)。 从“编程之美”的角度看,可以借用一句非常经典的话: “迭代是人,递归是神!” 来从宏观上对二者进行把握。 从概念上讲,递归就是指程序调用自身的编程思想,即一个函数调用本身;迭代是利用已知的变量值,根据递推公式不断演进得到变量新值得编程思想。 从直观上讲,递归是将大问题化为相同结构的小问题,从待求解的问题出发,一直分解到已经已知答案的最小问题为止,然后再逐级返回, 从而得到大问题的解(一个非常形象的例子就是分类回归树 classification and regression tree,从root出发,先将root分解为另一个(root,sub-tree),就这样一直分解,直到遇到leafs后逐层返回);而迭代则是从已知值出发,通过递推式,不断更新变量新值,一直到能够解决要求的问题为止。 以斐波那契数列的求解为例,通过两种典型的实现进行对比: fib(0)=0; fib(1)=1; fib(n)=fib(n-1)+fib(n-2); 递归的实现 [objc]

彻底理解递归,从递归的本质说起!

旧街凉风 提交于 2019-11-28 17:44:23
遍历二叉树,是学习树这种数据结构首先要理解的一种基本操作。比较简单地方式就是用递归去遍历,鉴于递归这种调用方法有一定的特殊性,今天还是想来讲讲怎么去理解递归遍历。本文针对想理解递归的过程的朋友,因为本人在学到这一部分的时候也纠结了很久,其实只要理解了过程,那以后写递归的代码再也不用“心虚”了,因为那个过程是可预测的,可证明的。 递归调用的特殊性在于自己调用自己,给人一种迷茫感,如果是递归调用“一次”,那还相对好理解,比如求阶乘的递归算法, int F(int n) { if(n==0)//递归边界 return 1; return n*F(n-1);//递归公式 } 一层一层调用,知道递归结束条件成立,再一层一层返回;但如果像二叉树是递归调用“两次”,似乎理解起来就不是很容易了。 void preorder(bintree t){ if(t){ printf("%c ",t->data); preorder(t->lchild); preorder(t->rchild); } } 对于一颗如下的二叉树,它的前序遍历顺序该怎么理解呢?我们今天来好好理一遍它的过程。 可以把递归看成是自己调用另一个和自己功能一样,但是函数名不同的函数来理解,或许看得更清楚明白,下面我们来看看这个前序遍历的过程是怎样的。 首先,我们记上面这个函数为F1,表示外层的函数,内层函数表示下一层的函数

LeetCode 刷题笔记——递归与回溯的理解

空扰寡人 提交于 2019-11-28 17:44:11
LeetCode 刷题笔记——递归与回溯的理解 马上就要入职了。在入职之前受师兄点拨,疯狂刷 LeetCode ,整个痛并快乐着的过程中,在算法和数据结构方面受益良多。 在刷题过程中,很快的就遇到了闻名已久的 递归 (Recursive) 。首次遇到递归,是 LeetCode 的第 17 题: Letter Combinations of a Phone Number 。解这道题的时候,虽然之前没有专门学过,但最先就想到了递归的解法,无师自通的把这个题解开了还让我得意了许久~ 不过后来又遇到了第 22 题: Generate Parentheses ,本来以为是一个很简单的,可以无脑用递归解决的问题,直接废了我一个上午…… 后来网上查了一下,它们说要用 回溯 (Backtrack) 的方法理解并解答。一看代码,形式同样也是反复调用函数自身,感觉这和递归并没什么区别啊? 于是多做了几道关于递归和回溯的问题,并在网上找了一些大神们的言论,自己对 递归 和 回溯 进行一些总结如下。 参考地址: 题库: LeetCode 递归与回溯的区别解释: 《关于递归与回溯比较通俗的方法》 《回溯和递归区别》 答题思路与源码 《leetcode 46. Permutations-全排列|回溯|递归|非递归》 《刷题笔记3(关于Permutation需要知道的事)》 《以Generate

硬核动图让你轻松弄懂递归,查找等概念

Deadly 提交于 2019-11-28 16:46:08
对于大部分人,数据结构一直是一个短板,当然我也是,不是学不会,而是容易忘,就拿最简单的排序来说吧,当时学习的时候明明已经弄得很清楚了,过了一段时间不用又忘记了,还要重新再看一遍,不知道有多少小伙伴和我有一样的烦恼。今天让我们用用动图的方式学习一下数据结构中的递归和二分查找吧,这种讲解方式非常生动,而且非常容易记住和理解。 一、递归 1.概念 递归简单的来说就是程序自己调用自己,就像下面这幅图一样,一直循环往复。 2.出口 如果程序一直这样循环往复的调用自己,一直都不结束,就是一个死循环, 这没什么意义。所以我们需要为递归定义一个结束条件,即递归的出口,当条件不满足时,递归一直前进,不断地调用自己;当边界条件满足时,递归返回。 递归的应用通常是把一个大型的比较复杂的问题,通过层层转化为一个与原问题相似的小的问题来求解,就像上边统计排队人数的问题。上边的这个小姐姐问第一个排队的人,有多少人排队,第一个人回答:我(1个人)+后边的人,小姐姐没有得到具体的答案,但是她知道只要弄清楚第一个人后边有多少人排队+第一个人就是排队的人数,所以她继续问后边的人,结果得到了相同的回答,于是她得到的答案变成了:1+1+后边的人。于是她不得不一直这样问下去,等到问到最后一个人的时候,最后一个人回答,就我一个人,到此刻小姐姐终于得到了想要的答案即:1+1+········+1。上边就是一个经典的递归的例子

Algorithm lesson final exam

走远了吗. 提交于 2019-11-28 16:27:23
1、algorithm analysis O B/W/AV/AMOR,混入其他问题,设计+分析 2、传统算法(肯定要考) 1)divide and conquer master therem、 recursive tree、分析复杂度、递归树加起来得到最终结果 2)greedy algorithm example sort->select 拟阵 独立系统的贪心模板,直接得到近似比 3)dynamic programming sub-optimal structrue、编辑距离 3、graph algorithm 1)exproration bfs and dfs、最小生成树 2)最短路,single path all pair 负环、负边 3)max-flow 优化方式 4、turing machine Np/NPC NP-hard np-reduction 5、approximation greedy/sequential/local search/lp rouding 三种算法的设计、图算法、图灵机、近似算法 来源: https://www.cnblogs.com/elpsycongroo/p/11939165.html

递归转迭代实操记录

跟風遠走 提交于 2019-11-28 15:24:11
针对那些经典的像素游戏设计的自动切图工具里用到种子填充算法的实现。 一开始是用递归实现的,后来遇到一些头像之类的比较大一点的图素,运行的时候经常占满C#默认的1M线程栈内存而崩溃。尝试使用各种多线方式改造并没有成功,于是干脆改成迭代形式,创建一个Stack自己完全精确控制其中的数据操作。 这里截取一段改成迭代后的代码,这是窗体的事件处理用cs代码。因为只是个小工具,没有完全把界面和逻辑分离。 //堆栈最大深度 private const int MaxStackFrames = 640 * 480; private Stack<FillStackFrame> mStack = new Stack<FillStackFrame>(MaxStackFrames); private void fillRegion(int x, int y) { //防止多线程操作堆栈引起的问题 lock (this) { //从UI初始化本次调用不会变的参数 int distance = Convert.ToInt32(txtDistance.Text); //复位堆栈并且压入初始数据 mStack.Clear(); var frame = new FillStackFrame(); frame.x = x; frame.y = y; mStack.Push(frame); /

递归介绍

怎甘沉沦 提交于 2019-11-28 14:52:22
  在C++语言中, 递归调用(recursive call)就是某一方法调用自身 。这种自我调用通常是直接的,即在函数体中包含一条或多条调用自身的语句。递归也可能以间接的形式出现,即某个方法首先调用其它方法,再辗转通过其它方法的相互调用,最终调用起始的方法自身。   递归的价值在于,许多应用问题都可简洁而准确地描述为递归形式。以操作系统为例,多数文件系统的目录结构都是递归定义的。具体地,每个文件系统都有一个最顶层的目录,其中可以包含若干文件和下一层的子目录;而在每一子目录中,也同样可能包含若干文件和再下一层的子目录;如此递推,直至不含任何下层的子目录。通过如此的递归定义,文件系统中的目录就可以根据实际应用的需要嵌套任意多层(只要系统的存储资源足以支持)。   以下将从递归的基本模式入手,循序渐进地介绍如何选择和应用( 线性递归、二分递归和多分支递归等 )不同的递归形式,以实现( 遍历、分治等 )算法策略,以及如何利用 递归跟踪和递推方程等方法分析递归算法的复杂度 。    一、线性递归   数组求和问题: 1 sum(int A[],int n) //传入的参数是数组长度 2 { 3 if (n < 1) //平凡情况:递归基 4 return 0; //直接计算(非递归式) 5 else //一般情况 6 return sum(A,n - 1) + A[n-1] ; //递归

别再翻了,面试二叉树看这 11 个就够了~

此生再无相见时 提交于 2019-11-28 14:29:22
写在前边 数据结构与算法: 不知道你有没有这种困惑,虽然刷了很多算法题,当我去面试的时候,面试官让你手写一个算法,可能你对此算法很熟悉,知道实现思路,但是总是不知道该在什么地方写,而且很多边界条件想不全面,一紧张,代码写的乱七八糟。如果遇到没有做过的算法题,思路也不知道从何寻找。面试吃了亏之后,我就慢慢的做出总结,开始分类的把数据结构所有的题型和解题思路每周刷题做出的系统性总结写在了 Github。欢迎关注和 star: 「 数据结构与算法仓库 」 PS:如果你刚刚在学习数据结构和算法,请务必把最简单的题弄懂,所有的入门的数据结构与算法从简单到复杂进行了全面的梳理。 「 初学者必会的 30 道数据结构与算法 」 如果你对数据结构和算法有了一定的了解和认识,上边的入门算法题已经可以轻松实现,那么可以尝试着解决 LeetCode 上总结的 30 道题,我把解题思路、测试用例、代码实现做了详细的整理,建议先自己尝试的解决哦,收藏 + 关注,欢迎 Star。「 必会的 30 道 LeetCode 经典算法题 」 如果你正在面试,经典的《剑指offer》所有的面试代码实现 (JavaScript 版)放在 Github 仓库,可自行查看。Github 地址「 剑指 offer 所有题目 JavaScript 版解题思路、总结、代码测试。✍️✍️✍️ 」 网络协议原理: 除了算法之外

第三章笔记:归纳,递归及化简

守給你的承諾、 提交于 2019-11-28 13:42:17
摘要:1. 介绍 2.基于归纳法与递归法的设计 3. 更强的假设条件 4.不变式与正确性 5. 松弛法与逐步完善 6. 归简法 + 换位法 = 困难度证明 7. 一些解决问题的建议 本章专注于讨论算法设计的基础技能。本章主题思想 归纳(induction)递归(recursion)及归简(reduction),通常会忽略掉问题的大部分内容,并将讨论聚焦于其解决方案中的某个单一步骤。而最妙的事情在于,该步骤恰是我们所需要的全部,有了它,其余问题迎刃而解。这些解决方案是由密切联系的。某种意义上,归纳法和递归法之间互为镜像,而两者都可以视为归简法的具体示例。 归简法指的是将某一问题转化成另一个问题。我们通常都会倾向于将一个未知问题归简成一个已解决的问题。归简法可能会涉及输入(操作中可能会遇到的新问题)与输出(已经解决的原问题)之间的转化。 归纳法(或者说数学归纳法)则被用于证明某个语句对于某种大型对象类(通常是一些自然数类型)是否成立。我们首先要证明语句在某一基本情况下(例如当数字为1时)是成立的,然后证明它可以由一个对象“推广到”下一个对象(如果其对于n-1成立,那么它对于n也成立)。 递归法则主要被用于函数自我调用时。在这里,我们需要确保函数在遇到基本情况时的操作是正确的,并且能将各层递归调用的结果组合成一个有效的解决方案。 其中,归纳法与递归法都倾向于将问题归简(或分解