递归


  递归,一个看似不简单,其实确实不简单的算法。但既然有这么种算法,必定是用来简化问题的,就看你是否抓住它的命脉所在。
  遇到问题,首先要判断,这个题是否能够用递归的方法解决,以及,用递归的方法相比而言(或者对你而言)是不是更简单的方法。怎么判断呢?首先得知道递归算法是什么吧。
  程序直接或间接调用自身的编程技巧称为递归算法。。。
  看似精辟,实则没任何用的一句话。这让我想起来曾经的数学课本上那些定理法则的定义,着实没用啊!应该不可能有人看到这句话就能领悟:噢,这就是递归。如果有,那就不是天才这么简单了。。。
  扯远了。相信在学习函数时,就已经知道递归函数的概念了,一般碰到的典例就是求阶乘了吧。这种函数的调用自身的方法叫做递归调用,而以此方式(通过编程)处理问题的方即为递归算法。从中抽离出的思想就是将一个大型的,复杂的问题,层层转化为一个或几个原问题相似的规模较小简单的问题,这才是你用来判断是否能够用递归算法解决的问题的判断标准。从其中我们理解到,遇到的问题较为复杂,但它却能层层分解开来,编程与之相比较简单的问题,且与原问题相似,并且还要注意到,它不一定只会简化为一个问题。碰到这样的问题时,我们该意识到需要递归了。
  知道知道了大体上是怎样实现的,但解决问题的具体步骤呢?偷个懒..在这里插入图片描述
  老师的总结总是精辟的,换而言之,看到这个你也不会懂的。寻找递归关系是解题最重要的一步,但在我看来,一开始就直接寻找递归关系不是个好的选择。倘若你费好大的劲终于找出的递归关系,却发现走不到最后怎么办,就好像你决定好走那条路,走下去却发现你的必经之路是一处绝地怎么办。固然可以从头来过,但花费的时间可弥补不回来。因此,不如先寻找到问题的已知条件和存在的停止边界(最小规模最简单的问题),然后寻找已知条件与哪些边界之间存在关系,再去思考递归关系,以及如何递归。当然,真正的问题难度都在递归关系上,鉴于我做题不多,不见得这之间有什么区别,但无论怎样,适合自己的才最好吧。我的方法当然适合自己咯。
  当然了,纸上谈兵,说的再好都是隔空对喊,两边都聋了。整例题吧。
  全排列问题。
  首先考虑下,边界问题。自己用手指头数数也能知道,数越多越难排,所以数少了就能找到它的边界。当然,此时是假设你还不知道这个题可用递归的方法做。
  如果有一个数,不用排。
  两个数,相互交换得出两种情况。
  三个数,为方便书写,或者以免遗漏也会将第一个数相同的放在一起。如此,递归的命脉已经默默浮出水面了,你也已经发现这个题要用递归的方法来解决了。
  因为当第一位数相同时,剩下两位数能够组成的排列,恰恰就与两个数时方法相同,如此类推,当给出的数很多时,就先把首位排好,在考虑剩下的数,并以相同的方法处理,以此类推,最终得出全部的排列方案。如此,这个问题的递归关系便已经解决了,同时,这个问题也解决了大半了,剩下的就是写代码了。在这里插入图片描述
  代码无声胜有声,将list数组中从下标为k到m的数据进行全排列。但注意红色部分将其复原的目的是避免排列下一个高位时原本应该作为下一个高位数的位置变化,否则就乱了。
  这样这个问题就算解决了。那在延伸一下,怎样使排列出的数按照从小到大输出呢?
  想要解决这个问题,需要理解整个过程数据是怎样变动的。以交换的方式选择出一个数作为最高位放在首位,那么原来的首位去了哪呢?自然去了选出的最高位那了,即(四位数为例):
  1234 2134 3214 4231
可以看到,前两个还可以做到当前高位的情况下是最小,但后两个就已经做不到了,那这样也直接可以写出最小的了:
  1234 2134 3124 4123
当写下这些数时,就已经可以发现,排列高位后剩下的需要从小到大排列,如此,这个问题就解决了。在这里插入图片描述
  这样,就能做到从小到大排列了。不过,这样这个题就完美了吗?没有。你怎样确定这个数组中的数原本就是从小到大排列的呢?所以在主函数中,对数组赋值后要紧跟着进行一次排序,这样这个题才是真正做完了。
  回头看一下这个问题,只是找到已知条件和边界再找出递归关系能够解决问题,但应付不了多变的情况,只有真正掌握好数据的走向才能无惧多变的现实。也正因此我才特别钟情c++对于数据流的概念,更为形象的说,数据就像是水流,而语言便是堵截水流的工具,算法便是你用以堵截水流的方法。水势莫测,工具多变,但只要你明白让水流以怎样的方式流淌,没有克服不了的困难。各种算法其实都一样,不过是变换着方法对数据进行着围追堵截,但究其根源,不过是要数据能够以你的意志流转。但水势莫测,变幻万千,千里之堤亦可瞬间溃于蚁穴,同样方法解决的问题也各有千秋,想要抓住数据的源头,唯有大量的做题才能渐渐摸索数据的踪迹,让它曲折蜿蜒,流淌出美丽的弧线!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值