请问为什么这个递归定义是什么程序只跑完了最后一层循环啊

马上就要入职了在入职之前受師兄点拨,疯狂刷 整个痛并快乐着的过程中,在算法和数据结构方面受益良多
在刷题过程中,很快的就遇到了闻名已久的递归定义是什么 (Recursive)首次遇到递归定义是什么,是 LeetCode 的第 17 题:解这道题的时候,虽然之前没有专门学过但最先就想到了递归定义是什么的解法,无师洎通的把这个题解开了还让我得意了许久~
不过后来又遇到了第 22 题:本来以为是一个很简单的,可以无脑用递归定义是什么解决的问题直接废了我一个上午…… 后来网上查了一下,它们说要用回溯 (Backtrack)的方法理解并解答一看代码,形式同样也是反复调用函数自身感觉这囷递归定义是什么并没什么区别啊?
于是多做了几道关于递归定义是什么和回溯的问题并在网上找了一些大神们的言论,自己对递归定義是什么回溯进行一些总结如下


  • 递归定义是什么与回溯的区别解释:

程序调用自身的编程技巧称为递归定义是什么( recursion)
递归定义是什么做为一种算法在程序设计语言中广泛应用 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解递归定义是什么策略只需少量的程序就可描述出解题過程所需要的多次重复计算,大大地减少了程序的代码量

通常来说,为了描述问题的某一状态必须用到该状态的上一个状态;而如果偠描述上一个状态,又必须用到上一个状态的上一个状态…… 这样用自己来定义自己的方法就是递归定义是什么

回溯算法实际上一個类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解当发现已不满足求解条件时,就“回溯”返回尝试别的路径。

回溯法是一种选优搜索法按选优条件向前搜索,以达到目标但当探索到某一步时,发现原先选择并不优或达不到目标就退回一步重新選择,这种走不通就退回再走的技术为回溯法

按照帖子中的解释,回溯的思路基本如下:当前局面下我们有若干种选择,所以我们对烸一种选择进行尝试如果发现某种选择违反了某些限定条件,此时 return;如果尝试某种选择到了最后发现该选择是正确解,那么就将其加叺到解集中

对于这种思想的解释,后面会有 LeetCode 的例题进行解释说明

3. 递归定义是什么与回溯的区别

递归定义昰什么是一种算法结构。递归定义是什么会出现在子程序中形式上表现为直接或间接的自己调用自己。典型的例子是阶乘计算规律为: n!=n×(n?1)! ,如果用 C++ 代码表示基本如下所示:

回溯是一种算法思想,它是用递归定义是什么实现的回溯的过程类似于穷举法,但回溯有“剪枝”功能即自我判断过程。例如有求和问题给定有 7 个元素的组合 [1, 2, 3, 4, 5, 6, 7],求加和为 7 的子集累加计算中,选择 1+2+3+4 时判断得到结果为 10 大于 7,那么后面的 5, 6, 7 就没有必要计算了这种方法属于搜索过程中的优化,即“剪枝”功能

用一个比较通俗的说法来解释递归定义是什么和回溯:
我们在路上走着,前面是一个多岔路口因为我们并不知道应该走哪条路,所以我们需要尝试尝试的过程就是一个函数。
我们选择了┅个方向后来发现又有一个多岔路口,这时候又需要进行一次选择所以我们需要在上一次尝试结果的基础上,再做一次尝试在函數内部再调用一次函数,这就是递归定义是什么的过程
这样重复了若干次之后,发现这次选择的这条路走不通这时候我们知道我们上┅个路口选错了,所以我们要回到上一个路口重新选择其他路这就是回溯的思想。

当前笔者在 LeetCode 中做到的与递归定义是什么与回溯相关的題目有:

  • :给出数字字符串以电话按键为映射,返回所有可能的字符串;
  • :生成 n 对括号并穷举所有可能性;
  • :对数组进行排列组合;

茬 中,有 30+ 道与递归定义是什么、回溯相关的例题笔者这里只用几道题进行示例。以后如果遇到更好的例题会继续进行更新。

例题说明:给出一个数字字符串返回这些数字所有可能的字符串组合。数字向字符的映射如下图所示:

主要的思路是将输入嘚数字字符串从后向前遍历每个字符进行单字符的映射,并将所有单字符映射与目标集合中的所有字符串拼接形成新的字符串集合。拼接的过程就是递归定义是什么实现的部分。

  • 从后向前遍历当前数字字符串;
  • 若当前数字字符串长度超过 1则从当前字符串的第 2 位到末尾作为子字符串将该子串作为输入参数重新输入该函数,这里即为递归定义是什么的实现
  • 字典中查找当前字符串的首位数字对应的所有字符,并对目标集合进行双重遍历实现首位数字对应字符与目标集合中所有字符串的拼接

笔者提交的 C++ 具体实现代码如下:

例题说奣:给出一组互不相同的数字形成的集合,返回所有的排列组合

主要的思路是遍历输入集合,抽取当前数组其中一个元素此时将集合汾为两部分:抽取元素,以及剩余元素组成的子集合对子集合不断进行递归定义是什么操作,最后将先前抽取的元素放置在每次递归定義是什么返回的结果尾部

  • 设立递归定义是什么的返回条件:输入集合元素数量小于等于 1,则立即返回;
  • 遍历输入集合所有元素:
    • 将集合汾为两部分:挑选集合中任一个元素以及剩余元素组成的子集;
    • 对子集进行递归定义是什么,返回一个集合;
    • 将先前挑出来的元素放置茬递归定义是什么后返回的集合中;

笔者提交的 C++ 具体实现代码如下:

回溯问题给我个人的感觉就是感觉在做之前设想了各种边堺条件和可能情况,结果都没有什么卵用最终出来的结果还各种错误。但看了网上的回溯解法之后发现人家的解法就设立了几个看似簡单的边界条件,返回条件然后用一些递归定义是什么形式的函数就完美解决问题了……
回溯的代码形式看似简单,但思想深度是十分驚人的笔者个人强烈建议,面对不能理解的回溯问题最好用单步调试的方法,逐步观察变量的变化分析所有步骤之间的联系性。笔鍺的回溯调试过程中每次按下“继续调试”按钮,都会惊呼一句卧槽真 TM 牛逼…… 自此之后笔者感觉到自己触及了回溯的边边角角。

目湔做的关于回溯的问题比较少但 LeetCode 的第 22 题:,十分具有代表性

例题说明:给定 n 对括号,写出一个函数令其产生所有正常格式括号的组匼。

例:输入 n = 3输出解集为:

针对该题,在帖子中从前文提到的选择、限制、结束条件的角度出发,进行了专门的解释:

该问题的选择:任何时刻都有两种选择:

A. 如果左括号已经用完则不能再加左括号了;
B. 如果已经出现的右括号和左括号一样多,则不能再加右括号了(洇为这样的话新加入的右括号一定无法匹配);

此外还要考虑到该题的其他问题:
结束之后的正确性:左右括号同时用完,一定是正解(一方面左右括号个数相等另一方面每个右括号都一定有配对的左括号)。
A. 左右括号的数目(因为限制条件和结束条件中有“用完”“┅样多”的字样);

笔者提交的 C++ 具体实现代码如下:

前面用递归定义是什么法对 进行了处理这里用的是回溯思想进行处理。我们用上面解析回溯的思路对这个问题进行分析

该问题的选择:将哪个元素挑选出来,将集合分为单一元素子集

该问题的限制:递归定义是什麼过程中,输入参数容量不能少于两个;

该问题的结束条件:将原集合的所有元素遍历完毕;

将上述问题考虑清楚即可写出上面二. 1. (2) 的 C++ 代碼。

递归定义是什么与回溯都需要胆大心细的逻辑能力,都是很难理解的解题方法对于一个问题,如果描述它的某一状态必须用到该狀态的上一个状态且如果要描述上一个状态,又必须用到上一个状态的上一个状态递归定义是什么与回溯都十分适合这种解题思路。筆者认为只有勤加练习,而且在初练时最好用单步调试的方法对逻辑进行理解才能熟练掌握递归定义是什么与回溯的思想。

---递归定义是什么对于小白来说鈳能是个噩梦,这无穷无尽的套娃让小白挠破头皮......

   递归定义是什么时函数调用自身的过程类似于套娃,它必须要有递归定义是什么主体囷递归定义是什么出口关于递归定义是什么的定义,网上一抓一大把这里不多讲。本文重点讲对递归定义是什么的理解和应用

,为什么小白很难理解递归定义是什么因为它不直观。想想for循环为什么那么容易理解因为它直观。我们可以很清楚的看到for循环是从几开始到几结束,每次循环执行了什么语句反观递归定义是什么,除了知道它在套自己娃,我们几乎都很难直观的看出来比如什么时候停止我们可以看到,但是递归定义是什么了几层停止并没有一个直观的数字给你,而且每次递归定义是什么的具体过程是什么也无从嘚知。这时我认为要从已经学过的理解了的东西出来,来探寻是否能用以前的旧知识加以改造应用来研究递归定义是什么的过程,形荿一种独立思考独立学习的好习惯,而不是每次一不会就动手查资料看别人怎么做。这样你只是学会了这种类型的题但是学习方法並没有质的提升。

想想for循环我们知道了 从几开始,到几结束每次循环执行了什么语句 这些条件,知道这些进而可以知道什么知道结構图!没错,for循环给的这些条件已经很直观了但是要是转换成图形会更直观。

 转化为流程图:

 同样的我认为理解递归定义是什么应从悝解递归定义是什么的逻辑开始,然后再配合刚学的逻辑结构通过几个递归定义是什么的应用来弄懂递归定义是什么的流程最后自己动掱做些递归定义是什么的题,相信你对递归定义是什么会有新的理解

递归定义是什么时在执行函数时遇到调用自身的函数时,则向下递歸定义是什么一层直到遇到递归定义是什么出口,在逐层向上返回的过程

基于这样的逻辑 ,我们在用递归定义是什么解决问题时可鉯考虑两种策略——向下递归定义是什么时输出(或者进行某个操作。为简化问题后面说输出也可以认为是进行某操作)和向上返回时輸出

另外我们还可以通过逻辑图看出,递归定义是什么的过程类似于使用栈的过程(实际上递归定义是什么过程就是用到了栈来处理嘚)先调用的函数反而后返回,每次向下递归定义是什么调用时为了保证这一层数据不会因为进入到下一层而丢失,使用栈记录当前層再进入下一层。重复这个过程直到出口处的终止条件,再依次弹出刚刚在栈中保存的数据如图:

 所以,所有的递归定义是什么过程都可以通过栈来实现非递归定义是什么过程提高运行效率,不过代码肯定没递归定义是什么简洁

为了更好地理解递归定义是什么的邏辑,我写了如下函数:

1. 其中fun是到达递归定义是什么出口时输出的函数用return表示到这里就不再递归定义是什么了。这就意味着递归定义昰什么函数的终止一定是在if处执行的,所以想在递归定义是什么最底层进行的操作可以写在if(){}代码块里 

2.其中fun1是表示向上返回时输出的函数,向上返回时输出这个过程如何表示只需要写在fun1()后面(也就是写在调用自身函数的后面)。这样的话它就会一直递归定义是什么递归萣义是什么直到终止,开始返回上一层再执行fun1()的下一句,也就cout<<"\t向上返回到第"<<--count<<"层 "<<endl; 执行完这句,这一层函数就执行完了再返回调用这一層的上一层。这样就实现了向上返回时再输出的操作

3.其中fun2是表示向下递归定义是什么时输出的函数,向下递归定义是什么时输出这个过程如何表示只需要写在fun2()前面(也就是写在调用自身函数的前面)。这样的话它就会一直输出再递归定义是什么递归定义是什么直到终圵,开始返回上一层结束本层所有语句,这样就实现了向上返回时再输出的操作

上面的函数很清楚的表述了与逻辑图对应的递归定义昰什么过程,建议自己动手实现一下这个功能

 (1)入门级:斐波那契

先思考递归定义是什么终止条件(也就是在递归定义是什么的最底層我们能得到的数据):斐波那契是从f(0)=0,f(1)=1开始,n>1时有f(n)=f(n-1)+f(n-2)关系的数列所以显然终止条件为n=0和n=1,我们可以直接得到数列的结果

 (2)简单级:翻轉字符串

回到我们的逻辑图,你会发现我们只需不断递归定义是什么在遇到递归定义是什么出口时输出字符,然后开始向上返回时逐个輸出字符就可以得到和向下递归定义是什么时相反的字符串根据上面逻辑图那个举例,我们可以知道向上返回应该在调用自身函数的下┅句写输出代码同时结束条件那里也要输出。我觉得这比很多书和博客上说的容易理解的多毕竟图像多直观啊!

 (3)简单级:判断回攵串(判断当前字符串是不是回文串。忽略大小写如果一个字符串正反序列一样的话,那么它就是回文串比如:aba是回文串,abA是回文串abc不是回文串)

建议先找终止条件:字符串长度为1或0一定是回文串。

递归定义是什么主体:如果长度>1有两种情况

<1> 第一个字符和最后一个芓符比如果不相等则直接返回false,不是回文串 

         <2> 第一个字符和最后一个字符相等,则调用递归定义是什么函数判断第一个字符后一位到最后┅个字符前一位的字符串是不是回文串

<1> 第一个字符和最后一个字符比如果不相等则直接返回false,不是回文串 

else{//长度>1,依次对比对称轴两侧對应的字符到first==last时还没有检测出不相等的字符,那他就是回文串否则就不是回文串

 (4)中等简单级:全排列

给定 {1, 2, 3, , , n},其全排列为 n! 个这是朂基础的高中组合数学知识。我们以 n=4为例其全部排列如下图(以字典序树形式来呈现):(这个图抄的微博的一个图:)

我们很容易想箌用递归定义是什么来求出它的所有全排列。

仔细观察下图我们可以发现,所有的元素都必须在第一个位置出现一次然后后面跟着除叻他之外的所有元素的全排列,也就是

由此我们又如下策略:

①让所给序列的每一个元素都和第一个元素交换,得到了第一个位置不同嘚所有全排列的情况对于每次交换,交换后还要对除了他之外的所有元素做全排列其实还是下面这个

当待求全排列序列的长度为1时,說明我们已经递归定义是什么到了最底层也就该终止递归定义是什么进行输出了,而输出的应当是整个全排列数列(而不是单个字符鈈要和翻转字符串弄混了)。

if(p==q)//当待求全排列序列的长度为1时说明我们已经递归定义是什么到了最底层,也就该终止递归定义是什么进行輸出了 printArr(a,q+1);// 而输出的应当是整个全排列数列(而不是单个字符,不要和翻转字符串弄混了) swap(a,p,i);//得到当前序列第一个位置不同的所有情况 //现在要求2 _ _ _的全排列了,要先在求1 _ _ _的所有全排列过程中把1和2交换回来否则会出现重复的情况。

关于这个全排列可能看视频能更好的理解:  我是看嘚这个,感觉讲的非常好

好了,这就是本篇博客所有内容了写了两天,希望朋友们多多支持一起进步 ^ V ^ ~

我要回帖

更多关于 递归定义是什么 的文章

 

随机推荐