普及层次第三讲递归递推分治

合集下载

普及层次第三讲递归递推分治

普及层次第三讲递归递推分治

方法2
将硬币分为8组,每组2个,每组比 较一次,若发现轻的,则为伪币。 最多可能有8次比较。
方法3
分析
上述三种方法,分别需要比较15次,8次,4 次,那么形成比较次数差异的根本原因在 哪里? 方法1:每枚硬币都至少进行了一次比较,而 有一枚硬币进行了15次比较 方法2:每一枚硬币只进行了一次比较 方法3:将硬币分为两组后一次比较可以将 硬币的范围缩小到了原来的一半,这样充 分地利用了只有1枚伪币的基本性质。
化简后:
q(n) = n(n+1)/2 +1;
例3.2.3 平面分割 设平面上有n条封闭曲线, 而任何两条封闭曲线恰好相交于两点,且任 何三条封闭曲线不相交于同一点,求这些封 闭曲线把平面分割成的区域个数。
14
2
1 1 2 3 4
8 1 10 11 6 8 9 2 1
6 3 4 7 12
3
5 4 7
[算法分析] 利用递推公式进行求解,因为N 不大于100, 因此定义数组时10个下标变量就足够了。 为了避免反复过程调用,我们采用以下主要步骤: 1、先利用双重循环将10以内的方案数计算后,存放在数组A 中; 2、输入N; 3、在一重循环中,利用公式直接求和。 4、输出方案数K。 [程序清单] 略 [运行数据及测试结果] N=2 K=2 N=7 K=4 N=16 K=10 N=20 K=10 N=100 K=38
求斐波那契数列中的第n个数
用递归的方法
用非递归的方法
begin function fib(n:integer):integer; f[0]:=0; begin f[1]:=1; if n=0 then fib:=0 readln(n) ; else if n=1 then fib:=1 for m:=1 to n do fib:=fib(n-1)+fib(n-2); f[m]:=f[m-1]+f[m-2]; end; writeln(‘f[’,n,‘]=’,f[n]) end.

递归、递推、分治

递归、递推、分治

分析
• 题目中的图明显是一棵树 • cost(Sj)公式的特点是sum{dist(i, j) * Si}
分析
• 递归计算一棵树能算出根节点的cost • 但是其他的节点怎么办呢?
• 递归计算可以算出以某个节点为根的树的 cost值 • 这个是这个节点的cost的一部分,而不是 全部 • 只需要将两一部分计算出来即可
• 通过对比左子树的中序与后序排列,找出 左子树的根节点…… • 将问题能够被递归描述。
• 当找到最后一个根节点时,递归无法再进 行下去,这就是递归结束的边界条件。
Hanoi
• 汉诺塔问题是源于印度一个古老传说的益 智玩具。上帝创造世界的时候做了三根金 刚石柱子,在一根柱子上从下往上安大小 顺序摞着64片 黄金圆盘。上帝命令婆罗门 把圆盘从下面开始按大小顺序重新摆放在 另一根柱子上。并且规定,在小圆盘上不 能放大圆盘,在三根柱子之间一次只能移 动一个圆盘。
• F(n) = F(n - 1) + F(n - 2) • M的范围如果特别大怎么办?
最大连续子ቤተ መጻሕፍቲ ባይዱ和
• 一个长为n(n<=10000)整数数列,找出其 中连续的子列,使其和最大。输出最大子 列和。
• 序列的子序列 序列M:-3 -2 4 2 -1 M的子序列有 (1)含有1个数的子序列有5个: -3; -2; 4; 2; -1; (2)含有2个数的子序列有4个: -3,-2; -2,4; 4,2; 2,-1; ...
分析
• 利用归并排序的思想求解逆序对的个数, 该算法的时间复杂度为O(nlogn)。 • 分治?
分析
• 将序列A一分而二,分为两个序列B和C • 如果求出了B和C序列的逆序对数,那么怎 么计算A的序列的逆序对数 • 在递归求解B和C两个序列的逆序对个数以 后,对B和C两个序列进行排序后,统计两 个序列之间的逆序对个数十分容易 • B: 6 5 4 2 • C:6 3 2 2 • B中的6 5 4与C中的3、2和2产生逆序对

递推-递归-分治-回溯

递推-递归-分治-回溯

递推算法在程序编辑过程中,我们可能会遇到这样一类问题,出题者告诉你数列的前几个数,或通过计算机获取了数列的前几个数,要求编程者求出第N项数或所有的数列元素(如果可以枚举的话),或求前N项元素之和。

这种从已知数据入手,寻找规则,推导出后面的数的算法,称这递推算法。

典型的递推算法的例子有整数的阶乘,1,2,6,24,120…,a[n]=a[n-1]*n(a[1]=1);前面学过的2n,a[n]=a[n-1]*2(a[1]=1),菲波拉契数列:1,2,3,5,8,13…,a[n]=a[n-1]+a[n-2](a[1]=1,a[2]=2)等等。

在处理递推问题时,我们有时遇到的递推关系是十分明显的,简单地写出递推关系式,就可以逐项递推,即由第i项推出第i+1项,我们称其为显示递推关系。

但有的递推关系,要经过仔细观察,甚至要借助一些技巧,才能看出它们之间的关系,我们称其为隐式的递推关系。

下面我们来分析一些例题,掌握一些简单的递推关系。

例如阶梯问题:题目的意思是:有N级阶梯,人可以一步走上一级,也可以一步走两级,求人从阶梯底走到顶端可以有多少种不同的走法。

这是一个隐式的递推关系,如果编程者不能找出这个递推关系,可能就无法做出这题来。

我们来分析一下:走上第一级的方法只有一种,走上第二级的方法却有两种(两次走一级或一次走两级),走上第三级的走法,应该是走上第一级的方法和走上第二级的走法之和(因从第一级和第二级,都可以经一步走至第三级),推广到走上第i级,是走上第i-1级的走法与走上第i-2级的走法之和。

很明显,这是一个菲波拉契数列。

到这里,读者应能很熟练地写出这个程序。

在以后的程序习题中,我们可能还会遇到菲波拉契数列变形以后的结果:如f(i)=f(i-1)+2f(i-2),或f(i)=f(i-1)+f(i-2)+f(i-3)等。

我们再来分析一下尼科梅彻斯定理。

定理内容是:任何一个整数的立方都可以写成一串连续的奇数和,如:43=13+15+17+19=64。

递归和分治的关系

递归和分治的关系

分治算法是一种算法设计思想,其主要思想是将一个复杂的问题分解为两个或更多相同或相似的子问题,直到子问题简单到可以直接解决。

然后,再将子问题的解合并,形成原问题的解。

这种算法设计思想常用于数据结构和算法设计中,如排序算法(如快速排序和归并排序)、二叉树操作等。

递归与分治的关系
递归是一种编程或函数自我调用的方法,递归函数会不断地调用自身,直到满足某个终止条件。

分治算法常常使用递归作为其实现手段,通过递归调用来实现问题的分解和解的合并。

这种情况下,递归就成为了实现分治的一种手段。

虽然分治算法常常依赖于递归来实现,但并不是所有的递归算法都是分治算法。

分治算法的关键在于解决问题的方式:它把一个问题分解为若干个独立的子问题,然后对子问题求解,最后合并子问题的解来得到原问题的解。

而递归只是一种函数自我调用的编程技巧,其并没有明确规定问题需要如何被分解和求解。

示例:归并排序
归并排序就是一个典型的分治算法。

归并排序首先将一个待排序的序列分解为两个或更多的子序列,然后对每个子序列进行排序,最后将排序后的子序列合并为一个有序序列。

递归、分治、动态规划、回溯

递归、分治、动态规划、回溯
正整数n的划分数p(n)=q(n,n).
n = 1, m = 1 n<m n=m n > m >1
递归举例
Hanoi塔问题 例6 Hanoi塔问题 设a,b,c是3个塔座.开始时,在塔座a上有一叠共n个圆 盘,这些圆盘自下而上,由大到小地叠在一起.各圆 盘从小到大编号为1,2,…,n,现要求将塔座a上的这一 叠圆盘移到塔座b上,并仍按同样顺序叠置.在移动圆 盘时应遵守以下移动规则: 规则1:每次只能移动1个圆盘; 规则2:任何时刻都不允许将较大的圆盘压在较小的圆盘 之上; 规则3:在满足移动规则1和2的前提下,可将圆盘移至 a,b,c中任一塔座上.
边界条件
递归方程
A(1,0) = 2 A(0, m) = 1 m≥0 n≥2 A(n,0) = n + 2 A(n, m) = A( A(n 1, m), m 1) n, m ≥ 1
递归举例
例3 Ackerman函数 函数 当一个函数及它的一个变量是由函数自身定义时,称这 个函数是双递归函数 双递归函数. 双递归函数 Ackerman函数A(n,m) A(n, Ackerman A(n m)定义如下:
递归举例
例1 阶乘函数 阶乘函数可递归地定义为:
边界条件
n=0 1 n!= n(n 1)! n > 0
递归方程 边界条件与递归方程是递归函数的二个要素,递归函 数只有具备了这两个要素,才能在有限次计算后得出 结果.
递归举例
Fibonacci数列 例2 Fibonacci数列 无穷数列1,1,2,3,5,8,13,21,34,55,…,被 称为Fibonacci数列.它可以递归地定义为:
A(n,m)的自变量m的每一个值都定义了一个单变量函数: M=0时,A(n,0)=n+2 M=1时,A(n,1)=A(A(n-1,1),0)=A(n-1,1)+2,和A(1,1)=2故 A(n,1)=2*n M=2时,A(n,2)=A(A(n-1,2),1)=2A(n-1,2),和 A(1,2)=A(A(0,2),1)=A(1,1)=2,故A(n,2)= 2^n .

递推-递归-分治-回溯

递推-递归-分治-回溯

递推算法在程序编辑过程中,我们可能会遇到这样一类问题,出题者告诉你数列的前几个数,或通过计算机获取了数列的前几个数,要求编程者求出第N项数或所有的数列元素(如果可以枚举的话),或求前N项元素之和。

这种从已知数据入手,寻找规则,推导出后面的数的算法,称这递推算法。

典型的递推算法的例子有整数的阶乘,1,2,6,24,120…,a[n]=a[n-1]*n(a[1]=1);前面学过的2n,a[n]=a[n-1]*2(a[1]=1),菲波拉契数列:1,2,3,5,8,13…,a[n]=a[n-1]+a[n-2](a[1]=1,a[2]=2)等等。

在处理递推问题时,我们有时遇到的递推关系是十分明显的,简单地写出递推关系式,就可以逐项递推,即由第i项推出第i+1项,我们称其为显示递推关系。

但有的递推关系,要经过仔细观察,甚至要借助一些技巧,才能看出它们之间的关系,我们称其为隐式的递推关系。

下面我们来分析一些例题,掌握一些简单的递推关系。

例如阶梯问题:题目的意思是:有N级阶梯,人可以一步走上一级,也可以一步走两级,求人从阶梯底走到顶端可以有多少种不同的走法。

这是一个隐式的递推关系,如果编程者不能找出这个递推关系,可能就无法做出这题来。

我们来分析一下:走上第一级的方法只有一种,走上第二级的方法却有两种(两次走一级或一次走两级),走上第三级的走法,应该是走上第一级的方法和走上第二级的走法之和(因从第一级和第二级,都可以经一步走至第三级),推广到走上第i级,是走上第i-1级的走法与走上第i-2级的走法之和。

很明显,这是一个菲波拉契数列。

到这里,读者应能很熟练地写出这个程序。

在以后的程序习题中,我们可能还会遇到菲波拉契数列变形以后的结果:如f(i)=f(i-1)+2f(i-2),或f(i)=f(i-1)+f(i-2)+f(i-3)等。

我们再来分析一下尼科梅彻斯定理。

定理内容是:任何一个整数的立方都可以写成一串连续的奇数和,如:43=13+15+17+19=64。

递归与递推——精选推荐

递归与递推——精选推荐

递归与递推递推递归递归:从已知问题的结果出发,⽤迭代表达式逐步推算出问题的开始的条件,即顺推法的逆过程,称为递归。

递推:从已知道的若⼲项出发,利⽤递推关系依次推算出后⾯的未知项的⽅法,我们称为递推算法。

递推与递归不同:递归是从未知到已知逐步接近解决问题的过程,⽽递推从已知到未知。

递推算法是⼀种⽤若⼲步可重复运算来描述复杂问题的⽅法。

递推是序列计算中的⼀种常⽤算法。

通常是通过计算前⾯的⼀些项来得出序列中的指定项的值。

递推的关系式可以暴枚找规律,也可以化繁为简,例如铺砖问题,最后⼀列砖铺与不铺,以及最后两列砖铺与不铺的情况相加即可求出关系式。

⽽关于递归,就是函数中再次调取函数,从⽽使困难的问题化为“1+1”类型简单的问题,得出结果再还原,操作过程类似于“U”型。

递归的重点是找到递归关系和递归出⼝。

……(概念太多,直接摆题)经典例题统计奇数和偶数个3内存限制:128 MiB时间限制:1000 ms标准输⼊输出题⽬类型:传统评测⽅式:⽂本⽐较题⽬描述在所有的N位正整数中,有多少个数中有偶数个数字3?⼜有多少个数有奇数个3?由于结果可能很⼤,你只需要输出这个答案对12345取余的值。

输⼊格式输⼊⼀个数N(1<=N<=1000),输⼊形式为⽂件输⼊,以读到0或⽂件末尾结束。

输出格式对于每⼀个N位正整数,输出有多少偶数个3以及多少奇数个3,中间⽤空格隔开。

样例样例输⼊2样例输出73 17数据范围与提⽰分别找出奇数偶数的递推式样例说明:在所有的2位数字,包含0个3的数有72个,包含2个3的数有1个,共73个对于⼀位数,除3外,其他全为含有偶数个三(数组元素初始化),紧接着,对于两位数,13,23,30~39(除33外)【这⾥有9个数,也可以进⾏思考】,43,53,63,73,83,93含有奇数个三,再看三位数(差不多就可以找到规律……)。

声明:a数组存储含奇数个三的个数,b数组⽤于存储偶数i的数值 1 2 3 ……a[i] 1 17 674 ……b[i] 8 73 226 ……So,a[i]=(b[i-1]+a[i-1]*9)%12345,b[i]=(a[i-1]+b[i-1]*9)%12345;#include<cstdio>using namespace std;int main(){int n,a[10005],b[10005];a[1]=1,b[1]=8;for(int i=2;i<=1001;i++){a[i]=(b[i-1]+a[i-1]*9)%12345;b[i]=(a[i-1]+b[i-1]*9)%12345;}while(scanf("%d",&n)!=EOF){if(n==0)return 0;printf("%d %d\n",b[n],a[n]);}return 0;}Hanoi塔内存限制:128 MiB时间限制:1000 ms标准输⼊输出题⽬类型:传统评测⽅式:⽂本⽐较题⽬描述问题的提出:Hanoi塔由n个⼤⼩不同的圆盘和三根⽊柱a,b,c组成。

递归与分治策略讲义课件(ppt 65页)

递归与分治策略讲义课件(ppt 65页)
int prev,now,next,j; if (n<=1) return(1);
else {
prev=1; now=1; for(j=2;j<=n;j++) {
next=prev+now; prev=now; now=next; } return(next); } }
具有编译递归程序能力的程 序设计语言有:C、Pascal 、 ALGOL、 PL/A 、 ADA、 QBASIC等,不具有编译递归 程序能力的程序设计语言有: FORTRAN、 COBOL、BASIC、 低级语言。
Hanio(3,A,B,C) Hanio(2,A,C,B)
Move (A,C)
Hanio(2,B,A,C)
结束
Hanio(2,A,C,B)
Hanio(1,A,B,C) Move (A,B)
Hanio(1,C,A,B)
Hanio(1,A,B,C) Move (A,C)
Hanio(1,C,A,B) Move (C,B)
例3 Hanoi塔问题
设x,y,z是3个塔座。开始时,在塔座x上有一叠共n个圆盘,这 些圆盘自下而上,由大到小地叠在一起。各圆盘从小到大编号 为1,2,…,n,现要求将塔座x上的这一叠圆盘移到塔座z上,并仍 按同样顺序叠置。在移动圆盘时应遵守以下移动规则:
规则1:每次只能移动1个圆盘;
规则2:任何时刻都不允许将较大的圆盘压在较小的圆盘之上;
(1)运行开始时,首先为递归调用建立一个工作栈,其结 构包括值参、局部变量和返回地址;
(2)每次执行递归调用之前,把递归函数的值参和局部变 量的当前值以及调用后的返回地址压栈;
(3)每次递归调用结束后,将栈顶元素出栈,使相应的值 参和局部变量恢复为调用前的值,然后转向返回地址指定 的位置继续执行。

递归与分治PPT课件

递归与分治PPT课件
递归元
2021/5/21
• 递归算法的思想是将对较大规模的对象的操 作归结为对较小规模的对象实施同样的操作。
• 这种规模的变化就体现在递归算法的变元中 的一类(一个或几个)变元上,这类变元被称 之为递归元。
• 递归元的变化是在递归定义中确定的,它的 变化应能导致递归算法的终止。
• 在递归算法的设计中递归元是非常重要的。
不大于m的划分个数记为q(n, m),可以建立
如的q(下n二,的元m递)递{归归关函1 系数::
n=1或
• 最m简i=f (单1n 情< 1形) :|| ((m1)<q1(n) , 1)r=e1t,uqrn(10,;m) =1 n, q(inf,(nm=) = 1)1|+| (qm(n=,=n–11) )return 1; n ≤ m m≥i1f ;(n == 1)q|(|n(,nm<–m1))+q(rne–tumr,nm1) +nq>(nm, >n–11);
一6,个5+划1分, 4。+2正, 4整+1数+n1的, 3不+同3, 的3+划2+分1的, 个
3数+成1+为1+正1 整数n的划分数,记作ρ(n)。
2+2+2, 2+2+1+1, 2+1+1+1+1,
2021/5/21
1+1+1+1+1+1
5
第5页/共57页
正整数的划分
• 在正整数的所有不同划分中,将最大加数n1
2021/5/21
若~为除法,即n / b,则有:
T(n) = aT(n / b) + D(n)

递归与递推

递归与递推
ijfc(t:=<>n n*ijl)c(tnh-e1n); enbdem;gi-nsearch(t.left);
visit(t);
m-search(l.right); end; end;
精品PPT
三、递归算法(suàn fǎ)的执行过程
n!1n(n1)!
n0 n0
主程序
=120
Fac(5)
=24
5*Fac(4)
end;
精品PPT
n皇后(huánghòu)问题
如何记录某个数字是否已经被使用过呢?很容 易想到可以用集合或者一维数组来实现。 比如我们(wǒ men)用一维数组hash[1..n]来记 录的话 hash[i]=1代表i已经被使用过 hash[i]=0代表i没有被使用过
同时我们(wǒ men)使用一个一维数组 result[1..n]来记录生成的全排列
精品PPT
汉诺塔问题(wèntí)
输入(shūrù):3 输出:
A->C A->B C->B A->C B->A B->C A->C
精品PPT
汉诺塔问题(wèntí)
只有一个盘子(pán zi)的移动:A C 两个盘子(pán zi)的移动:A B,A C,
BC n个盘子(pán zi)的移动(n>2): 将上面的n-1个盘子(pán zi)看成一个整体,
end.
精品PPT
四、应用(yìngyòng)举例—汉诺塔 问题
如图所示,我们有三根柱子(A、B、C)和若干大小 各异的圆盘,一开始的时候,所有圆盘都在A柱上, 且按照从小到大的顺序排列整齐(小的在上,大的在 下),现在请你把所有的圆盘从A柱搬到C柱上去。 在搬动的时候,一次只能将某柱最顶端的一个(yī ɡè) 圆盘移动到另一柱的最顶端,且在移动的过程中,永 远不允许出现大圆盘在小圆盘之上的情况。

递归与分治

递归与分治

分析
• 初看这个问题,似乎无从下手,于是我们 可以先考虑最简单的情况,既n = 2时
0 0 0 1
这时,无论公主在哪个格子,我们都可以 用一块毯子填满
分析
• 继续考虑n = 4的情况
我们已经知道了解决2 * 2的格子 中有一个障碍的情况如何解决,因 此我们可以尝试构造这种情况 首先,显然可以将4 * 4的盘面划 分成4个2 * 2的小盘面,其中一块 已经存在一个障碍了 而我们只需在正中间的2 * 2方格 中放入一块地毯,就可以使所有小 盘面都有一个障碍 于是,n = 4的情况就解决了
思考题3: 聪明的质监员
• 小 T 是一名质量监督员,最近负责检验一批矿产的质量。这批矿 产共有 n 个矿石,从 1到 n 逐一编号,每个矿石都有自己的重量 wi 以及价值 vi。检验矿产的流程是: 1、给定 m个区间[Li,Ri]; 2、选出一个参数 W; 3、对于一个区间[Li,Ri],计算矿石在这个区间上的检验值 Yi :
K (1≤K≤N-1)—
比赛既要讲求实力,又要考虑到运气。每头 奶牛都有一个BTP排名,恰为1-N。如果两 头奶牛的排名相差大于给定整数K,则排名靠 前的奶牛总是赢排名靠后的奶牛;否则,双 方都有可能获胜。
Answer—
现在观众们想知道,哪头奶牛是所有可能成 为冠军的牛中排名最靠后的。并要求你列举 出一个可能的比赛安排使该奶牛获胜。
思考题1:导线和开关
• 如上图是一个具有3根导线的电缆把A区和B区连接起来。 在A区3根导线标以1,2,3;在B区导线1和3被连到开关3, 导线2连到开关1。 • 一般说来,电缆含m(1≤m ≤90)根导线,在A区标以1,2,…,m。 在B 区有m个开关,标为1,2,… ,m。每一根导线都被 严格地连到这些开关中的某一个上; 每一个开关上可以连有 0根或多根导线。

递归与递推公式的掌握技巧

递归与递推公式的掌握技巧

递归与递推公式的掌握技巧掌握递归与递推公式的技巧在计算机科学领域中,递归和递推公式是重要的概念和工具。

递归是指在一个函数或过程内部调用自己,直到满足某个条件才返回结果。

递推公式是指通过前面的结果推导出后面的结果的公式,也称为递归公式。

递归和递推公式在算法设计、数据结构、数学等领域都得到了广泛应用。

递归和递推公式的掌握是编程和数学学习的重点之一。

在实际应用中,掌握递归和递推公式对程序的正确性、效率和可读性都是至关重要的。

本文将介绍如何掌握递归和递推公式的技巧,帮助读者更好地应用它们解决问题。

第一部分:递归的设计和实现递归的设计和实现是一项重要的技巧。

递归函数的设计和实现需要考虑以下几个方面:1.确定递归的终止条件递归的过程必须能够终止,否则会造成死循环或栈溢出等问题。

因此,在设计递归函数时必须确定递归的终止条件。

例如,计算斐波那契数列的递归函数可以定义如下:```int fibonacci(int n) {if (n <= 1) {return n;}else {return fibonacci(n - 1) + fibonacci(n - 2);}}```在这个例子中,当n小于或等于1时,递归终止,返回n的值。

如果n大于1时,递归调用fibonacci函数求解f(n-1)和f(n-2)的和。

递归终止条件的确定是函数正确实现的关键之一。

2.转化问题的规模递归通常是为了解决类似于“分而治之”的问题。

通过递归调用将原问题拆分成子问题,并在子问题得到解后合并得到原问题的解。

例如,快速排序算法就是一种递归的排序算法,它的实现如下:```void quick_sort(int arr[], int left, int right) {if (left < right) {int pivot = partition(arr, left, right);quick_sort(arr, left, pivot - 1);quick_sort(arr, pivot + 1, right);}}int partition(int arr[], int left, int right) {int pivot = arr[right];int i = left - 1;for (int j = left; j < right; j++) {if (arr[j] <= pivot) {i++;swap(&arr[i], &arr[j]);}}swap(&arr[i + 1], &arr[right]);return i + 1;}```在这个例子中,快速排序通过递归调用将原问题拆分为更小的子问题,并在子问题解决后进行合并。

递归分析和分治算法

递归分析和分治算法

递归分析和分治算法递归分析一般利用的方法是主定理,辅助的方法有替换法,递归树方法~主定理:递归树:主定理的证明可以通过递归树的方法进行;主定理适用的范围比较局限,有些情况不能被包括,这些情况就需要利用递归树的方法了,主定理的case1是f(n)小于n log b a多项式时间,原定理描述为f(n)=O(n log b a-ε)且ε>0,它与case2中f(n)=Θ(n log b a)中间差一些情况,就是f(n)小于n log b a,但是多余的不是多项式时间;另外就是case2和case3之间相差的部分,就是f(n)大于n log b a,但是如果不大于多项式时间,就不能满足主定理了;另外一种是case3中的f(n)不满足后面的情况;举个例子,如果最近点对中间利用快速排序进行排序,则合并时间nlgn,递归公式T(n)=2T(n/2)+nlgn,这种情况介于case2和case3,所以利用递归树:T(n)=nlgn+n(lgn-lg2)+n(lgn-lg4)+...=nlgnlgn-n(lg2+2lg2+3lg2+...+lgnlg2)=nlgnlgn-nlg2((1+lgn)lgn)/2=nlgnlgn=nlg2n;不过这里我查到mit给的主定理和算法导论有所不同,涵盖了上面的情况,如下:可能这算是一种情况来了;那么这里我在取一个不满足主定理的例子~所以主定理不满足时就利用决策树进行带入吧!如果数学计算能力比较强大还是可以计算出来的,毕竟主定理都是决策树证明的,数学能力不强表示证明有点困难...不过这里有个偷懒的证明方法,直接假设f(n)是一个n k形式的;T(n)=aT(n/b)+n kT(n/b)=aT(n/b2)+(n/b)k...所以T(n)=a(aT(n/b2)+(n/b)k)+n k=n k (1+a/b k+...+(a/b k)h)=(n k-n logba)/(1-a/b k),接下来讨论a和b k的关系决定了为n k还是n logba,上面如果为1则为n k log b n了。

传统基本算法(迭代、递归、分治)

传统基本算法(迭代、递归、分治)

传统基本算法(迭代、递归、分治)一,迭代与递推1)迭代法也称“辗转法”,是一种不断用变量的旧值递推出新值的解决问题的方法。

迭代算法一般用于数值计算。

迭代法应该是我们早已熟悉的算法策略,程序设计语言课程中所学的累加、累乘都是迭代算法策略的基础应用。

例如:斐波那契数列例子:兔子繁殖问题一对兔子从出生后第三个月开始,每月生一对小兔子。

小兔子到第三个月又开始生下一代小兔子。

假若兔子只生不死,一月份抱来一对刚出生的小兔子,问一年中每个月各有多少只兔子。

·问题分析因为一对兔子从出生后第三个月开始每月生产一对小兔子,则每月新下生的小兔子的对儿数显然由前两个月的小兔子的对儿数决定。

则繁殖过程如下:一月二月三月四月五月六月 ……1 1 1+1=2 2+1=3 3+2=5 5+3=8 ……·数学建模(斐波那契数列)y1=y2=1,yn=yn-1+yn-2,n=3,4,5,……2)倒推法的概念·倒推法:是对某些特殊问题所采用的违反通常习惯的,从后向前推解问题的方法。

例如,在不知前提条件的情况下,由结果倒过来推解它的前提条件,从而求解问题。

又如,由于存储的要求,而必须从后向前进行推算。

另外,在对一些问题进行分析或建立数学模型时,从前向后分析问题感到比较棘手,而采用倒推法,则问题容易理解和解决。

例子:穿越沙漠问题用一辆吉普车穿越1000公里的沙漠。

吉普车的总装油量为500加仑,耗油率为1加仑/公里。

由于沙漠中没有油库,必须先用这辆车在沙漠中建立临时油库。

该吉普车以最少的耗油量穿越沙漠,应在什么地方建油库,以及各处的贮油量。

·问题分析贮油点问题要求要以最少的耗油量穿越沙漠,即到达终点时,沙漠中的各临时油库和车的装油量均为0。

这样只能从终点开始向前倒着推解贮油点和贮油量。

·数学模型根据耗油量最少目标的分析,下面从后向前分段讨论。

第一段长度为500公里且第一个加油点贮油为500加仑。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

T(n)
=
n
T(n/2)
T(n/2)
T(n/2)
T(n/2)
递归与分治基本原理
将求出的小规模的问题的解合并为一个更大规模的问题 的解,自底向上逐步求出原来问题的解。
T(n)
n/2
=
n/2
n
n/2 n/2
T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4
例3.2.2 :切煎饼
王小二自夸刀工不错,有人放一张大的煎 饼在砧板上,问他:“饼不许离开砧板, 切100刀最多能分成多少块?”
找规律,如下图:
令q(n)为切n刀能分成的块数,从图中可见: q(1)=1+1=2 q(2)=1+1+2=4 q(3)=1+1+2+3=7 q(4)=1+1+2+3+4=11 在切法上让每两条线都有交点,则有 q(n)=q(n-1)+n q(0)=1
例3.2.5 汉诺塔问题,现在要求把全部 圆盘从A柱移到C柱的最小移动步数h(n)。
H(1)=1 H(2)=2*h(1)+1=3 H(3)=2*h(2)+1=7 H(4)=2*h(3)+1=15 H(5)=2*h(4)+1=31 …… h(n) =2*h(n-1)+1= 2^n-1
拓展:若是汉诺双塔呢?即:假如现在每 种大小的盘子都有两个,并且是相邻的, 设盘子个数为2n,问最小移动的步数? ⑴ 假如不考虑相同大小盘子的上下要多 少次移动,设移动次数为J(n);
递归的概念
直接或间接地调用自身的算法称为递归算法。用函数 自身给出定义的函数称为递归函数。 由分治法产生的子问题往往是原问题的较小模式,这 就为使用递归技术提供了方便。在这种情况下,反复 应用分治手段,可以使子问题与原问题类型一致而其 规模却不断缩小,最终使子问题缩小到很容易直接求 出其解。这自然导致递归过程的产生。 分治与递归像一对孪生兄弟,经常同时应用在算法设 计之中,并由此产生许多高效算法。
[算法分析] 利用递推公式进行求解,因为N 不大于100, 因此定义数组时10个下标变量就足够了。 为了避免反复过程调用,我们采用以下主要步骤: 1、先利用双重循环将10以内的方案数计算后,存放在数组A 中; 2、输入N; 3、在一重循环中,利用公式直接求和。 4、输出方案数K。 [程序清单] 略 [运行数据及测试结果] N=2 K=2 N=7 K=4 N=16 K=10 N=20 K=10 N=100 K=38
不难看出: K(2)=K(1)+1 K(3)=K(1)+1 K(4)= K(2)+K(1)+1 K(5)= K(2)+K(1)+1 ...... K(9)= K(3)+K(2)+K(1)+1 由此,总结出递推公式: K(N)= K(M)+K(M-1)+......+K(1)+1, 其中M=取整(开平方SQRT(N)或 SQR(N)(BASIC)。
化简后:
q(n) = n(n+1)/2 +1;
例3.2.3 平面分割 设平面上有n条封闭曲线, 而任何两条封闭曲线恰好相交于两点,且任 何三条封闭曲线不相交于同一点,求这些封 闭曲线把平面分割成的区域个数。
14
2
1 1 2 3 4
ቤተ መጻሕፍቲ ባይዱ
8 1 10 11 6 8 9 2 1
6 3 4 7 12
3
5 4 7
procedure search(w,n:integer); begin if w=0 then p:=p+1; if n>=1 then begin search(w-a[n],n-1); search(w,n-1) ; end; end;
递归转化为非递归
• 递归是算法设计中的一种重要方法, 它的优势在于能用有限的语句来定义对 象的无限集合。对于某些问题,用递归 处理起来简单明了,程序结构清晰、精 练,但是由于递归处理的过程需占用大 量的机时和空间,因而程序的效率低, 在必要的时候,需要将递归转化为非递 归来处理。
递推与递归
递归与递推表面看来是相逆的过程,其实也是相 似的,最终的计算都是从小算到大。 递推的使用环境要求高导致了递推的高效性,递 推没有重复计算什么数据,保持了高效。 递归大多数会重复计算子问题,导致时间浪费, 所以一般不要使用过深的递归,甚至会空间溢出。 但是也不能说递推好,递归差,因为递归却能解决 很多递推做不到的事情,在某些特定的环境下也能 实现高效,并且递归容易使用。我们要就事论事!
递归、递推、分治
南京第二十九中学 林晖
例3.1.1 背包问题
问题一:给定背包容量W和物体种类N,以及 每种物体的重量Wi,每种物体只有一个,问 是否能将背包装满。请统计箱装满的方案数
样例输入:5 4 1 2 3 4
样例输出:2
分析
对第n个物体,只有两种情况, 即取或者不取。 若取, 原问题就转化为search(w-a[n],n-1), 若不取, 则转化为search(w,n-1)。 若 w=0 则说明能够装满。
例3.3.1 :找出伪币
给你一个装有1 6枚硬币的袋子。1 6枚硬币中有一个是伪造的,并且那个 伪造的硬币比真的硬币要轻一些。你的 任务是找出这枚伪造的硬币。 为了帮助你完成这一任务,将提供 一台可用来比较两组硬币重量的仪器, 比如天平。利用这台仪器,可以知道两 组硬币的重量是否相同。
方法1
任意取1枚硬币,与其他硬币进行 比较,若发现轻者,这那枚为伪币。 最多可能有15次比较。
[问题分析]下面,我们罗列出N取不同值时的方案,以 便从中找到解决问题的方法。 N=1 K(1)=1 (1) N=2 K(2)=2 (2), (1,2) N=3 K(3)= 2 (3),(1,3) N=4 K(4)= 4 (4),(1,4),(1,2,4),(2,4) N=5 K(5)=4 (5),(1,5),(1,2,5),(2,5) N=6 K(6)= 4 (6),(1,6),(1,2,6),(2,6) N=9 K(9)=6 (9), (1,9), (1,2,9), (1,3,9),(2,9),(3,9)
非递归算法一般要比递归算法效率高得多。
求斐波那契数列中的第n个数
用递归的方法
用非递归的方法
begin function fib(n:integer):integer; f[0]:=0; begin f[1]:=1; if n=0 then fib:=0 readln(n) ; else if n=1 then fib:=1 for m:=1 to n do fib:=fib(n-1)+fib(n-2); f[m]:=f[m-1]+f[m-2]; end; writeln(‘f[’,n,‘]=’,f[n]) end.
三、分治
分治法的设计思想是:
将一个难以直接解决的大问题,分割成一些 规模较小的相同问题,以便各个击破,分而治之。 凡治众如治寡,分数是也。
----孙子兵法
递归与分治基本原理
对这k个子问题分别求解。如果子问题的规模仍然不够小, 则再划分为k个子问题,如此递归的进行下去,直到问题 规模足够小,很容易求出其解为止。
二、递推
递推算法:对于一个有规律的数列,我们可 以借助已知的项,利用特定的关系逐项推算出 它的后继项的,……,如此反复,直到找到所 需的那一项为止,这样的方法称为递推算法。
递推算法的首要问题是得到相邻的数据项间的关 系(即递推关系)。
解决递推问题的一般步骤
建立递推关系式 确定边界条件
递推求解
例3.2.1 NICOMACHUS (尼克马库斯)定理 [问题描述] NICOMACHUS定理:任何一个整数的立方都可以表 示成一串奇数的和,例如: 13=1 23=3+5=8 33=7+9+11=27 43=13+15+17+19=64 ...... 表示的规律: 分析:用 F(n) 表示 n 的3次方的数。 n为奇数: F(3) = (32-2)+32+(32+2) = 3*32=27 n为偶数: F(4) = ...... ……………..=4*42=64
方法1
假设袋中有n 个金块。可以用函数M a x通过 n-1次比较找到最重的金块。找到最重的金块 后,可以从余下的n-1个金块中用类似的方法 通过n-2次比较找出最轻的金块。这样,比较 的总次数为2n-3。 算法如下:
max:=a[1];min:=a[1]; for i:=2 to n do {2n-2次比较} begin if a[i]>max then max:=a[i]; if a[i]<min then min:=a[i]; end ;
分析: ⑴ 中的移动相当于是把前一个问题中的每个 盘子多移动一次,也就是: J(n) = 2*H(n) = 2*(2^n - 1) = 2^(n+1)-2
讨论交流:递归递推的关系
1、相互转换: 递归转递推 函数(过程)内部的“子过程”放 到循环体,边界相同 2、但是递推一定优越递归吗? 比如:快排换成递推如何实现 实现是可以的,用数组存放状态,模拟堆栈,但 要将递归转化递推,编写代码反而不易 总结:不能片面的说成递推的效率优于递归,得 会灵活应用,而且往往做题时,递归或递推的思路才 更重要。
方法2
将硬币分为8组,每组2个,每组比 较一次,若发现轻的,则为伪币。 最多可能有8次比较。
方法3
分析
上述三种方法,分别需要比较15次,8次,4 次,那么形成比较次数差异的根本原因在 哪里? 方法1:每枚硬币都至少进行了一次比较,而 有一枚硬币进行了15次比较 方法2:每一枚硬币只进行了一次比较 方法3:将硬币分为两组后一次比较可以将 硬币的范围缩小到了原来的一半,这样充 分地利用了只有1枚伪币的基本性质。
相关文档
最新文档