详细解说递归与分治算法,一文带你入门到熟悉

全文共 2114 字,阅读文本大概需要 3.8 分钟。

前言

这几天看到交流有人群里说有关递归的栈溢问题,刚好小编又看到有关递归的东西,给大家阐述一下递归和分治的内容,让各位更加理解有关前贤的各种化整为零。

正文

很多人认为递归是语言中最为难以理解的内容之一,其实不需要有什么特别对待,只要理解了有关地址,指针和栈的调用就会发现很平常,当然如果你看了一下下后面的内容你也会有此感。

首先递归的定义:

递归:参见“递归”

what?,这个定义什么也没说吧。

改一下吧

递归:如果还没有递归是什么意思,参见“递归”

哈哈!这次你应该就能明白了,递归原来就是“自己用到自己”。这个定义明显比上面的定义简介明了多了。既然明白了其中原理后,那就需用在继续参见下去了。当然这个让很多人感到有点东西的递归定义不止这些:

“A主管:这个事不归我管,你去找 B 主管吧。”你去了 B 那里

“B主管:这个事不归我管,你去找A 主管吧~” 你有回到了 A 这里

这种踢皮球原则想必有很多人碰到过,A,B主管的所言不变,假设你始终听话,你就会始终往复于此。(这个叫做:无限递归,这个是你个人和计算机无法忍受的)。上面的你并没有自己想往复与两个主管之间,这中“间接的使用自己”也是递归的一种形式。

这就是递归的定义,简洁而严密~

都讲递归使用到栈,上面的定义好像是少了点什么?了解一下栈的特点先进后出(FILO)结构,栈顶指针始终指向栈顶(如果不是太了解不急,我后面介绍)。现在要了解,如果语言执行一个函数的时候会有一栈帧——递归函数也是如此,每一次调用递归过程中都对产生一个栈帧实现参数的传递。并且跳到程序的开头。这时被调用的栈叫做堆栈段(这一段有自己的大小)这个也不能被越界,但是每次调用都会生成一个栈帧,在这个过程中可能会发生栈的溢出问题(不理解的话可以理解为上面主管的踢皮球你来回跑自己累的嗝屁了)。

上面的一段应该就是那种低层的让人很焦虑的东西。下面介绍几个小栗子

举栗子

为了让大家很熟悉就能理解。(分为几种情况举栗子,从简到繁)

我总结了递归问题的三找求解办法:

找重复(在重复中找到一种划分,通过递推公式或者等价转化成子问题)

找变化的量(变化的量通常是转化成参数的)

找到出口(根据参数变化规律找到边界条件,像上面的踢皮球问题总得把球把握在自己的手上)

单层递归问题 – n!阶乘问题(n >= 1)

首先找到重复的和变化的量 n!可以转化为 > n*(n-1)!> 直到 1 的阶乘为 1。为这个递归的出口条件。

通过分析可以很容易的写出递归定义:
《详细解说递归与分治算法,一文带你入门到熟悉》

有了递归定义就可以很简单的写出对应代码(代码获取方式在文末)

(Markdown 语法写出的代码格式无法显示换行,小编研究一下以后采用Markdown )

《详细解说递归与分治算法,一文带你入门到熟悉》

这个单层递归形式为线性的水花四溅复杂度为O(n)

双分枝递归问题 – Fibonacci 数列

斐波那契数列是一个很为经典多分枝递归问题,也叫做“兔子繁殖问题”。斐波那契数列的内容如下:无穷数列 1、1、2、3、5、8、13、21、34、55…这种后一项为前两项的和的数列(第1、2项已被定义)为 Fibonacci 数列。

这个问题可以等价为两个问题的子问题,两个子问题的和为整个问题。

由此可以写成函数的递归定义:

《详细解说递归与分治算法,一文带你入门到熟悉》

有了递归定义可以简单的写出对应的代码:

《详细解说递归与分治算法,一文带你入门到熟悉》

这个算法的时间复杂度为O(2(N/2))~~O(2N)

详细的计算见:https://bbs.pediy.com/thread-123051.htm

双递归函数 – Ackerman 函数(这个稍微有点难度)

这个函数是有两个自变量参数所构成,他的最为原始的形式可以到维基百科中浏览,这里介绍函数的一般形式。

直接给出定义:
《详细解说递归与分治算法,一文带你入门到熟悉》

这个递归函数中的有着多重递归的形式可以通过定义写出代码:

《详细解说递归与分治算法,一文带你入门到熟悉》

代码相对来讲比较简单,但是函数调用很多次如果想更加了解这个函数可以自己手动模拟ack(3,3)这个函数,最终答案为 61 。

递归经典问题 – Hanoi 塔问题

Hanoi 塔问题内容是:有a、b、c三个塔,初始状态是:在 a 塔上放了 n 个圆盘从上到下,从小到大。(大盘不允许放在小盘上)要求把 a 塔上的盘子放到 c 塔上。每次只能拿一个盘子。

为了更好的解决这个问题小编专门到 4399小游戏 上找了汉诺塔的游戏玩了一下。

首先要解决这个问题我们要知道把盘子移动到另一个柱子需要有一个柱子作为辅助。

这是我们就可以把问题理解为 1-n 从 a -> c ,c作为辅助

1.1 到 n-1 从 a 移动到 c ,b 为辅助

2.把第 n 个柱子移动到 b

3.1 到 n-1 从 c 移动到 b ,a 为辅助

《详细解说递归与分治算法,一文带你入门到熟悉》

通过递推公式T(n)=2T(n-1)+1

所以汉诺塔问题的时间复杂度为O(2^n)

相对于的问题还有:

二分搜索就是使用分治

二分查找的递归形式

希尔排序的问题

只要能实现主问题转化为多个小问题解决的基本都可以采用递归。还有一点是递归都可以转化为非递归形式。

今天只能写这么多了

真诚希望各位能够转发扩散

欢迎关注微信公众号:「挑战算法与程序设计」更多能容将在公众号第一时间推出

    原文作者:递归与分治算法
    原文地址: https://blog.csdn.net/tyh18226568070/article/details/83020487
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞