数据结构之递归法和分治法

一、递归与堆栈

1、递归(recursion)是指在定义自身的同时又出现了对自身的引用。如果一个算法直接或间接地调用自己,则称这个算法是一个递归算法。
2、递归由两部分组成:递归调用递归终止条件
3、递归解决的应用问题:
(1) 问题本身的定义就是递归,比如斐波那契数列、xn
(2)问题本身虽然不是递归定义,但是它所用到的数据结构是递归,比如链表、树;
(3)问题的解法满足递归的性质。
4、函数之间的调用,在运行被调用函数之前系统通常需要完成如下工作:
(1)对被调用函数的运行现场进行保护,主要是参数与返回地址等信息的保存;
(2)创建被调用函数的运行环境;
(3)将程序控制转移到被调用函数的入口。
在被调用函数执行结束返回函数之前,系统需要完成如下工作:
(1)保存被调函数的返回结果;
(2)释放被调用函数的数据区;
(3)依照保存的调用函数的返回地址将程序控制转移到调用函数。
5、以斐波那契数列说明递归实现过程(n=3):
递归调用示例
6、弊端:递归方法过于频繁的函数调用和参数传递,会增大系统开销。

二、基于归纳的递归

1、对于一个规模为n的问题P(n),归纳法的步骤:
(1)基本项:A1是问题P(1)的解;
(2)递归项:对于所有的k,1 < k < n,若Ak是问题P(k)的解, 则存在f 使得f(Ak)是P(k+1)的解,其中f是对Ak的某种运算或处理。
例题一:求解n阶汉诺塔问题。汉诺塔问题是由法国数学家 Edouard Lucas 在 1883 年发明的。n 阶汉诺塔问题可以描述为:假设有 X、Y、Z 三个塔座,初始时有 n 个大小不一的盘子按照从小到大的次序放在塔座 X 上。现在要求将塔座 X 上的所有盘子移动到塔座 Z 上并保持原来的顺序,在移动过程中要满足以下要求:在塔座之间一次只能移动一个盘子并且任何时候大盘子都不能放到小盘子上。
递归求解过程如下:
基本项:若只有一个盘子,则不需要使用过渡塔座,直接把它放到目的塔座即可。时间复杂度T(1) = 1
递归项:如果多于一个盘子,则需要将塔座 X 上的 1 到 n-1 个盘子使用 Z 作为过渡塔座放到塔座 Y 上,然后将第 n 个盘子(最后一个盘子)放到塔座 Z,最后将塔座 Y 上的 n-1个盘子使用塔座 X 作为过渡放到塔座 Z。时间复杂度T(n) = 2T(n-1)+1 =O (2n) 。

三、递推关系求解

求解递推关系的常用方法
1、数学归纳法:递归算法的时间复杂度是使用递推关系给出的,可以先观察前几项,最后得出时间复杂度。
2、迭代法:是迭代地展开递归方程的右端,使之成为一个非递归的和式,然后通过对和式的估计来达到对方程左端即方程的解的估计。这个方法估计递归方程解的渐近阶不要求推测解的渐近表达式,但要求较多的代数运算。
求解递推关系
3、递归树:在一棵递归树中,每个节点代表了一组递推表达式中函数符号所表示的子问题的代价。我们求出树中每层节点的代价之和就得到一层的代价和,然后我们将树中每层的代价和求出来就可以确定所有递归调用的代价。图
图2
图3

四、分治法

对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。这种算法设计策略叫做分治法。

1、基本思想

将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。如果原问题可分割成 k (1< k ≤ n)个子问题,并且这些子问题都是
可解的,进一步我们还可利用这些子问题的解求出原问题的解,那么此时使用分治法就是可行的。
例如:寻找具有 n 个元素的数组 a[0, n-1]中的最大与最小元素。

2、分治条件

(1)当问题的规模缩小到一定的程度时,可以较容易的解决;
(2)问题可以分解为许多小规模、类型相同的子问题,即该问题具有最优子结构性质;
(3)能够通过将子问题的解合并得到原问题的解;
(4)原问题分解出的各个子问题是彼此独立的,即子问题之间不存在公共的子问题

3、分治算法的步骤

分治在每一层递归都有三个步骤:
(1)分解:将原问题分解为若干个规模较小、相互独立、与原问题形式相同的子问题;
(2)解决:若子问题规模较小而且容易被解决,则直接解决;否认递归的求解各个子问题;
(3)合并:将各个子问题的解合并为原问题的解。

五、例题

一、递归例题

简单例题

例题一——面试题08.06:汉诺塔问题
例题二——938:二叉搜索树的范围和

中等例题

例题一——剑指Offer面试题16:数值的整数次方
例题二——Leetcode894:所有可能的满二叉树

困难例题

二、分治例题

简单例题
中等例题
困难例题
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值