最近经常遇到用迭代方法求解的问题和递归解法,容易混淆,所以这里是一.递归:
从例子中引出,看看递归典型案例中有哪些1.斐波那契数列
斐波那契数列又称黄金分割数列,是指1、1、2、3、5、8、13、21、……这样的数列
这个数列从第三项开始,各项等于前两项之和。2.
阶乘n!=n*(n-1 ) (n-2 )…(1)3.汉诺威问题4.全序列
从n个不同元素中任意提取m(dzdyc )个元素,按一定顺序排列,就是从n个不同元素中提取出m个元素的一个序列。 当m=n时,所有的排列情况称为全排列。
例如,1、2、3三种元素的全部排列如下。
1,2,3
一,三,二
2,1,3
2,3,1
3,1,2
3,2,1http://www.Sina.com/.两张有趣的图
即使现在说不出定义,我也能理解什么是递归了
5
递归是在运行中调用自己。
构成递归的必要条件:1.子问题与原问题相同,必须更简单;
2 .不能无限制呼叫本身。 需要出口。 简化为非递归情况处理。
递归到底是个啥
迭代的典型例子
1 .斐波那契数列(对,又是我) )。
2 .汉诺威问题(这个不巧吗) )。
3 .背包问题
有n个项目和容量为v的背包。 第I项的重量为w[i],价值为v[i]。 要求将哪些行李放入背包,使放入背包的行李重量的总和不超过背包的容量,价值的总和达到最大。 基本想法
这是最基本的背包问题,特点是每件物品只有一件,可以选择装不装。
子问题定义状态:即f[i][v]表示前I件物品正好放入容量为v的背包中所获得的最大价值。 其状态转移方程如下。
f[i][v]=max{ f[i-1][v],f[i-1][v-w[i]] v[i] }。
可以压缩空间,f[v]=max{f[v],f[v-w[i]] v[i]}
这个方程非常重要,基本上所有有关背包问题的方程都是从它派生出来的。 因此,有必要详细说明这个。 “将前I个项目放入容量为v的背包”的子问题可以转换为只涉及前i-1个项目的问题,前提是只考虑第I个项目的策略(放入还是不放入)。 如果不包含第I项,则问题将转换为“将第一个i-1项放入容量为v的背包”,价值为f[i-1][v]; 放入第I个物品后,问题转化为“将第一个i-1的物品剩余容量放入v-w[i]的背包中”,此时获得的最大价值是在f [i-1][v-w[i]]之外再放入第I个物品
注意,如果f[v]有意义,且只存在前I个物品的一个子集,则其总费用为f[v]。 因此,根据此方程完成递归后,最终的答案不一定是f[N] [V],而是f[N][0…V]的最大值。 如果从状态的定义中去掉“恰”字,转移方程中就会再加一个f[v-1]项,保证f[N] [V]是最后的答案。 http://www.Sina.com/http://www.Sina.com /
与反复和递归的关系不同(敲打黑板)
从概念上说,递归是程序调用自身的编程思想,即指向一个函数调用自身的迭代是利用已知变量值,通过递归公式不断演化得到变量新的有价值的编程思想。 简而言之,递归是指反复调用函数本身来实现循环。 迭代是函数中的一个代码实现循环,而迭代与普通循环的区别在于,参与循环代码中运算的变量是同时保存结果的变量,当前保存的结果是下一个循环计算的初始值。 http://www.Sina.com/http://www.Sina.com /
循环次数多时,迭代的效率明显高于递归。
以斐波那契数列求解为例,通过两种典型实现进行对比
递归实现
intfib(intn ) if ) N1 ) returnfib ) n-1 ) fib ) n-2 ); else return n; //n=0,1时,给予recursion结束条件}反复
intfib(intn ) { int i,temp0,temp1,temp2; if(n=1)返回n; 时间1=0; 时间2=1; for(I=2; i=n; I ) { temp0=temp1 temp2; 时间2=时间1; temp1=temp0; }返回时间0; }