《算法设计与分析》递归算法典型例题

合集下载

递归算法及经典例题详解

递归算法及经典例题详解

递归算法及经典例题详解
1.什么是递归
递归简单来说就是在运行过程中不断调用自己,直到碰到终止条件,返回结果的过程。

递归可以看作两个过程,分别是递和归。

递就是原问题把要计算的结果传给子问题;归则是子问题求出结果后,把结果层层返回原问题的过程。

下面设一个需要经过三次递归的问题,为大家详细看一下递归的过程:当然,现实中我们遇到递归问题是不会按照图中一样一步一步想下来,主要还是要掌握递归的思想,找到每个问题中的规律。

2.什么时候使用递归
递归算法无外乎就是以下三点:1.大问题可以拆分为若干小问题2.原问题与子问题除数据规模不同,求解思路完全相同3.存在递归终止条件
而在实际面对递归问题时,我们还需要考虑第四点:
当不满足终止条件时,要如何缩小函数值并让其进入
下一层循环中
3.递归的实际运用(阶层计算)
了解了大概的思路,现在就要开始实战了。

下面我们来看一道经典例题:
求N的阶层。

首先按照思路分析是否可以使用递归算法:
1.N!可以拆分为(N-1)!*N
2.(N-1)!与N!只有数字规模不同,求解思路相同
3.当N=1时,结果为1,递归终止
满足条件,可以递归:
publicstaticintFactorial(int num){if(num==1){return num;}return num*Factorial(num-1);}
而最后的return,便是第四步,缩小参数num的值,让递归进入下一层。

一般来说,第四步往往是最难的,需要弄清该如何缩
小范围,如何操作返回的数值,这一步只能通过不断
地练习提高了(当然如果你知道问题的数学规律也是
可以试出来的)。

算法设计与分析—递归算法

算法设计与分析—递归算法
return 4
4
2021/8/17
15
6.3递归算法的设计方法
递归算法既是一种有效的算法设计方法,也 是一种有效的分析问题的方法。递归算法求解 问题的基本思想是:对于一个较为复杂的问题, 把原问题分解成若干个相对简单且类同的子问 题,这样较为复杂的原问题就变成了相对简单 的子问题;而简单到一定程度的子问题可以直 接求解;这样,原问题就可递推得到解。
main()

4
x=17

bn = BSearch(a, x, 0, 7)
BSearch(a, x, 0, 7) … mid=3 …
return BSearch(a, x, 4, 7)
BSearch(a, x, 4, 7) …
4
mid=5 … return BSearch(a, x, 4, 4)
BSearch(a, x, 4, 4) … mid=4 …
2021/8/17
26
6.4递归过程和运行时栈
对于非递归函数,调用函数在调用被调用函 数前,系统要保存以下两类信息:
(1)调用函数的返回地址(从而能执行下一 语句);
(2)调用函数的局部变量值。
当执行完被调用函数,返回调用函数前,系 统首先要恢复调用函数的局部变量值,然后返回 调用函数的返回地址。
2021/8/17
10
递归调用的执行过程:
main() …… fn=Fact(3) ……
Fact (2) …… y=Fact(1) ……
return 2*y
Fact (0) ……
…… return 1
Fact (3) …… y=Fact (2) ……
return 3*y
Fact (1) …… y=Fact(0) ……

算法设计与分析课后习题

算法设计与分析课后习题

1、实验内容递归求n的二次方各项的系数。

2、程序设计代码如下:#include"stdio.h"void coeff(int a[],int n)if(n==1)a[1]=1;a[2]=1;elsecoeff(a,n-1);a[n+1]=1;for(int i=n;i>=2;i=i-1)a[i]=a[i]+a[i-1];a[1]=1;void main()int a[100],i,n;printf("输入n的值:");scanf("%d",&n);coeff(a,n);for(i=1;i<=n+1;i++)printf(" %d ",a[i]);printf("\n");1、实验内容写出计算ackerman函数ack(m,n)的递归计算函数。

2、程序设计代码如下:#include "stdio.h"int ack(int m,int n)if(m==0)return n+1;else if(n==0)return ack(m-1,1);elsereturn ack(m-1,ack(m,m-1));void main()int m,n,z;printf("input m and n:");scanf("%d %d",&m,&n);if(m<0 && n<0)printf("error input!");elsez=ack(m,n);printf("%d\n",z);第四章例15 求数列的最大子段和给定n个元素的整数列(可能为负整数)a1,a2,…..,an。

求形如:ai,ai+1,……aj i,j=1,…..,n,i<=j的子段,使其和为最大。

递归时间复杂度例题

递归时间复杂度例题

以下是递归时间复杂度的例子:
1.计算整数x的n次方
暴力算法的时间复杂度为O(n),空间复杂度为O(1)。

而使用递归算法,每次递归可以将问题规模减半,因此时间复杂度可以降低到O(logn),但空间复杂度会增加到O(logn)。

2.斐波那契数列
斐波那契数列是一个经典的递归问题,其定义如下:F(0) = 0,F(1) = 1,F(n) = F(n-1) + F(n-2)(n >= 2)。

如果直接使用递归算法来计算斐波那契数列的第n项,时间复杂度会达到O(2^n),因为会有很多重复的计算。

可以使用动态规划或记忆化搜索来优化算法,将时间复杂度降低到O(n)。

3.归并排序
归并排序是一种使用递归的排序算法,其基本思想是将待排序的数组分成两半,分别递归地对它们进行排序,然后将排好序的两个子数组合并成一个有序的数组。

归并排序的时间复杂度为O(nlogn),空间复杂度为O(n)。

4.汉诺塔问题
汉诺塔问题是一个经典的递归问题,其目标是将一堆大小不同的盘子从一个柱子移动到另一个柱子上,并满足以下条件:每次只能移动一个盘子;大盘子不能放在小盘子上面。

可以使用递归算法来解决汉诺塔问题,其基本思想是将问题分解成两个子问题:将上面的n-1个盘子从起始柱子移动到辅助柱子上,再将最大的盘子从起始柱子移动到目标柱子上,最后将n-1个盘子从辅助柱子移动到目标柱子上。

汉诺塔问题的时间复杂度为O(2^n),空间复杂度为O(n)。

这些例子表明,递归算法的时间复杂度和空间复杂度取决于问题的性质和递归的实现方式。

因此,在设计递归算法时,需要仔细分析问题,选择合适的递归策略,并进行适当的优化。

算法设计与分析习题第二章分治与递归

算法设计与分析习题第二章分治与递归

2010-12-28
12
2.11 编写针对链表的快速排序程序。
需要保存指针信息。下面给出双向链表的快速排序算法 void fast_sort( Sdata *a, Sdata *f, Sdata *t ) { Sdata *i,*j,k,p; i = f; j = t; if ( t->lnext != f ) { k = a->data; //用于比较的基准数值 i = f; j = t; p = -1; while ( j != i )
7
2.7 按2.2.4节的描述,编写从二叉树中删除一个结点 的C语言程序 二叉树节点删除有三种情况: (1)*p是叶子(即它的孩子数为0):无须连接*p的子树, 只需将*p的双亲*parent中指向*p的指针域置空即可。 (2)*p只有一个孩子*child:只需将*child和*p的双亲直接 连接后,即可删去*p。注意:*p既可能是*parent的左孩 子也可能是其右孩子,而*child可能是*p的左孩子或右孩 子,故共有4种状态。 (3)*p有两个孩子:先令q=p,将被删结点的地址保存在q 中;然后找*q的中序后继*p,并在查找过程中仍用parent 记住*p的双亲位置。*q的中序后继*p一定是 *q的右子树 中最左下的结点,它无左子树。因此,可以将删去*q的 操作转换为删去的*p的操作,即在释放结点*p之前将其 数据复制到*q中,就相当于删去了*q.
算法设计与分析习题
第二章 分治与递归
2010-12-28
1
2.1 对于顺序查找算法,分析目标值存在于数组中的 概率p趋于0的含义,这种情况下平均查找次数有什么 样的变化?当p趋于1时呢? 见教材P12。平均比较次数为 n - p(n-1)/2。 p趋于0,平均次数趋于n;p趋于1时,平均次数趋于 (n+1)/2。(求极限)

《算法设计与分析》递归算法典型例题

《算法设计与分析》递归算法典型例题

算法递归典型例题实验一:递归策略运用练习三、实验项目1.运用递归策略设计算法实现下述题目的求解过程。

题目列表如下:(1)运动会开了N天,一共发出金牌M枚。

第一天发金牌1枚加剩下的七分之一枚,第二天发金牌2枚加剩下的七分之一枚,第3天发金牌3枚加剩下的七分之一枚,以后每天都照此办理。

到了第N天刚好还有金牌N枚,到此金牌全部发完。

编程求N和M。

(2)国王分财产。

某国王临终前给儿子们分财产。

他把财产分为若干份,然后给第一个儿子一份,再加上剩余财产的1/10;给第二个儿子两份,再加上剩余财产的1/10;……;给第i 个儿子i份,再加上剩余财产的1/10。

每个儿子都窃窃自喜。

以为得到了父王的偏爱,孰不知国王是“一碗水端平”的。

请用程序回答,老国王共有几个儿子?财产共分成了多少份?源程序:(3)出售金鱼问题:第一次卖出全部金鱼的一半加二分之一条金鱼;第二次卖出乘余金鱼的三分之一加三分之一条金鱼;第三次卖出剩余金鱼的四分之一加四分之一条金鱼;第四次卖出剩余金鱼的五分之一加五分之一条金鱼;现在还剩下11条金鱼,在出售金鱼时不能把金鱼切开或者有任何破损的。

问这鱼缸里原有多少条金鱼?(4)某路公共汽车,总共有八站,从一号站发轩时车上已有n位乘客,到了第二站先下一半乘客,再上来了六位乘客;到了第三站也先下一半乘客,再上来了五位乘客,以后每到一站都先下车上已有的一半乘客,再上来了乘客比前一站少一个……,到了终点站车上还有乘客六人,问发车时车上的乘客有多少?(5)猴子吃桃。

有一群猴子摘来了一批桃子,猴王规定每天只准吃一半加一只(即第二天吃剩下的一半加一只,以此类推),第九天正好吃完,问猴子们摘来了多少桃子?(6)小华读书。

第一天读了全书的一半加二页,第二天读了剩下的一半加二页,以后天天如此……,第六天读完了最后的三页,问全书有多少页?(7)日本著名数学游戏专家中村义作教授提出这样一个问题:父亲将2520个桔子分给六个儿子。

算法分析与设计(答案)

算法分析与设计(答案)

算法分析与设计(答案)一:二分查找的递归实现算法import java.util.Arrays;import java.util.Scanner;public class BinSearch {public static int binsearch(int[]a,int start,int stop,int b){if(start>stop)return -1;int i=(start+stop)/2;if(a[i]==b)return i;if(a[i]>b)return binsearch(a,start,i-1,b);return binsearch(a,i+1,stop,b);}/***@param args*/public static void main(String[] args) {// TODO Auto-generated method stubScanner sc=new Scanner(System.in);int n=sc.nextInt();int a[]=new int [n];System.out.println("输入数组元素");for(int i=0;i<n;i++){a[i]=sc.nextInt();}Arrays.sort(a);System.out.println("排序后的数组为");for(int i=0;i<a.length;i++){System.out.print(a[i]+" ");}System.out.println();System.out.println("输入要查找的数");int b=sc.nextInt();int x=binsearch(a,0,n-1,b);if(x==-1){System.out.println(b+"不在数组中,请输入另一个数");b=sc.nextInt();x=binsearch(a,0,n-1,b);}System.out.println(b+"在数组中的第"+(x+1)+"个位置");}}二:Ackerman函数的递归实现算法import java.util.Scanner;public class Test2 {private static int akm(int n, int m) {// 递归设计int r, g;if (n == 1 && m == 0)r = 2;else if (n == 0 && m >= 0)r = 1;else if (m == 1)r = n * 2;else if (m == 2)r = (int) Math.pow(2, n);else if (m == 0 && n >= 2)r = n + 2;else {g = akm(n-1, m);r = akm(g, m-1);// 两次连着递归}return r;}public static void main(String[] args) {try {System.out.println("请输入1个大于等于0的整数:");Scanner sc = new Scanner(System.in);int n = sc.nextInt();System.out.println("请再输入1个大于等于0的整数:");int m = sc.nextInt();System.out.println(akm(n, m));} catch (Exception e) {}}}三:全排列的递归实现算法import java.util.Scanner;public class AllSort{//全排列public static void main(String[] args) {Scanner sc=new Scanner(System.in);System.out.println("输入需要全排列的元素个数");int n=(char) sc.nextInt();int buf[]=new int [n];System.out.println("请依次输入每一个元素");for(int i=0;i<n;i++){buf[i]=sc.nextInt();}perm(buf,0,buf.length-1);}public static void perm(int[] buf,int start,int end){ if(start==end){//当只要求对数组中一个元素进行全排列时,只要就按该数组输出即可(特殊情况)for(int i=0;i<=end;i++){System.out.print(buf[i]);}System.out.println();}else{//多个字母全排列(普遍情况)for(int i=start;i<=end;i++){//(让指针start分别指向每一个数)int temp=buf[start];//交换数组第一个元素与后续的元素buf[start]=buf[i];buf[i]=temp;perm(buf,start+1,end);//后续元素递归全排列temp=buf[start];//将交换后的数组还原buf[start]=buf[i];buf[i]=temp;}}}}四:快速排序的递归实现算法import java.util.Scanner;public class QuickSort {public static int []a;public static void quicksort(int p,int r){if(p<r){int q=partition(p,r);quicksort(p,q-1);quicksort(q+1,r);}}public static int partition(int p,int r){int i=p,j=r+1;int x=a[p];while(true){while(a[++i]<x&&i<r);while(a[--j]>x);if(i>=j)break;int temp=a[i];a[i]=a[j];a[j]=temp;}a[p]=a[j];a[j]=x;return j;}/***@param args*/public static void main(String[] args) {// TODO Auto-generated method stubScanner sc=new Scanner(System.in);System.out.println("输入要排序的数组长度");int n=sc.nextInt();a=new int[n];System.out.println("输入"+n+"个元素");for(int i=0;i<n;i++)a[i]=sc.nextInt();quicksort(0,n-1);System.out.println("排序后的数组为");for(int j=0;j<a.length;j++)System.out.print(a[j]+" ");}}五:整数划分的递归实现算法import java.io.IOException;import java.util.*;public class ZhengshuHuafen {public static int a=0 ;public static int Devide(int input, int base, int []pData, int index){if(input<1||base<1)return 0;if(input==1||base==1){if(input==1){pData[index] = input;print(pData, index+1);}else{for(int k=0; k<input; k++){pData[index++] = base;}print(pData,index);}return 1;}if(input==base){pData[index] = base;print(pData,index+1);int temp = Devide(input,base-1,pData,index);return 1 + temp;}if(input<base){int temp = Devide(input,input,pData,index);return temp;}else{pData[index] = base;int temp1 = Devide(input-base,base,pData,index+1); int temp2 = Devide(input,base-1,pData,index);return temp1 + temp2;}}public static void print(int []pData ,int index){String s = new String();for(int i = 0 ; i < index - 1 ; i++){System.out.print(pData[i]+"+");s += String.valueOf(pData[i]);s += "+"; }System.out.println(pData[index-1]);s += String.valueOf(pData[index-1]) +"\r\n";}public static void main(String[] args) {int n ;Scanner in = new Scanner(System.in) ;System.out.print("请输入一个整数") ;n = in.nextInt() ;System.out.println("你刚才输入的数为"+n) ;int []pdata = new int[n] ;a=Devide(n, n, pdata, 0) ;System.out.println(""+a) ;}}六:合并排序的递归实现算法import java.util.Scanner;public class mergeSort {public static int []b;public static void mergeSort1(int []a,int left,int right) {if(left<right){int i=(left+right)/2;mergeSort1(a,left,i);mergeSort1(a,i+1,right);merge(a,b,left,i,right);copy(a,b,left,right);}}public static void merge(int []c,int []d,int l,int m,int r) {int i=l;int j=m+1;int k=l;while((i<=m)&&(j<=r))if(c[i]<=c[j])d[k++]=c[i++];else d[k++]=c[j++];if(i>m)for(int q=j;q<=r;q++)d[k++]=c[q];elsefor(int q=i;q<=m;q++)d[k++]=c[q];}public static void copy (int[]c,int[]b,int left,int right) {for(int i=left;i<=right;i++){c[i]=b[i];}}public static void main(String[]args){Scanner sc=new Scanner(System.in);int n=sc.nextInt();b=new int[n];int []a;a=new int [n];for(int i=0;i<n;i++){a[i]=sc.nextInt();}mergeSort.mergeSort1(a,0,n-1);for(int j=0;j<=n-1;j++)System.out.print(a[j]+" ");}}。

《算法设计与分析》递归算法典型例题

《算法设计与分析》递归算法典型例题

算法递归典‎型例题实验一:递归策略运‎用练习三、实验项目1.运用递归策‎略设计算法‎实现下述题‎目的求解过‎程。

题目列表如‎下:(1)运动会开了‎N天,一共发出金‎牌M枚。

第一天发金‎牌1枚加剩‎下的七分之‎一枚,第二天发金‎牌2枚加剩‎下的七分之‎一枚,第3天发金‎牌3枚加剩‎下的七分之‎一枚,以后每天都‎照此办理。

到了第N天‎刚好还有金‎牌N枚,到此金牌全‎部发完。

编程求N和‎M。

(2)国王分财产‎。

某国王临终‎前给儿子们‎分财产。

他把财产分‎为若干份,然后给第一‎个儿子一份‎,再加上剩余‎财产的1/10;给第二个儿‎子两份,再加上剩余‎财产的1/10;……;给第i个儿‎子i份,再加上剩余‎财产的1/10。

每个儿子都‎窃窃自喜。

以为得到了‎父王的偏爱‎,孰不知国王‎是“一碗水端平‎”的。

请用程序回‎答,老国王共有‎几个儿子?财产共分成‎了多少份?源程序:(3)出售金鱼问‎题:第一次卖出‎全部金鱼的‎一半加二分‎之一条金鱼‎;第二次卖出‎乘余金鱼的‎三分之一加‎三分之一条‎金鱼;第三次卖出‎剩余金鱼的‎四分之一加‎四分之一条‎金鱼;第四次卖出‎剩余金鱼的‎五分之一加‎五分之一条‎金鱼;现在还剩下‎11条金鱼‎,在出售金鱼‎时不能把金‎鱼切开或者‎有任何破损‎的。

问这鱼缸里‎原有多少条‎金鱼?(4)某路公共汽‎车,总共有八站‎,从一号站发‎轩时车上已‎有n位乘客‎,到了第二站‎先下一半乘‎客,再上来了六‎位乘客;到了第三站‎也先下一半‎乘客,再上来了五‎位乘客,以后每到一‎站都先下车‎上已有的一‎半乘客,再上来了乘‎客比前一站‎少一个……,到了终点站‎车上还有乘‎客六人,问发车时车‎上的乘客有‎多少?(5)猴子吃桃。

有一群猴子‎摘来了一批‎桃子,猴王规定每‎天只准吃一‎半加一只(即第二天吃‎剩下的一半‎加一只,以此类推),第九天正好‎吃完,问猴子们摘‎来了多少桃‎子?(6)小华读书。

第一天读了‎全书的一半‎加二页,第二天读了‎剩下的一半‎加二页,以后天天如‎此……,第六天读完‎了最后的三‎页,问全书有多‎少页?(7)日本著名数‎学游戏专家‎中村义作教‎授提出这样‎一个问题:父亲将25‎20个桔子‎分给六个儿‎子。

【分析】算法分析与设计作业参考答案

【分析】算法分析与设计作业参考答案

【关键字】分析《算法分析与设计》作业参考答案作业一一、名词解释:1.递归算法:直接或间接地调用自身的算法称为递归算法。

2.程序:程序是算法用某种程序设计语言的具体实现。

2、简答题:1.算法需要满足哪些性质?简述之。

算法是若干指令的有穷序列,满足性质:1)输入:有零个或多个外部量作为算法的输入。

2)输出:算法产生至少一个量作为输出。

3)确定性:组成算法的每条指令清晰、无歧义。

4)有限性:算法中每条指令的执行次数有限,执行每条指令的时间也有限。

2.简要分析分治法能解决的问题具有的特征。

分析分治法能解决的问题主要具有如下特征:1)该问题的规模缩小到一定的程度就可以容易地解决;2)该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质;3)利用该问题分解出的子问题的解可以合并为该问题的解;4)该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。

3.简要分析在递归算法中消除递归调用,将递归算法转化为非递归算法的方法。

将递归算法转化为非递归算法的方法主要有:1)采用一个用户定义的栈来模拟系统的递归调用工作栈。

该方法通用性强,但本质上还是递归,只不过人工做了本来由编译器做的事情,优化效果不明显。

2)用递推来实现递归函数。

3)通过Cooper变换、反演变换能将一些递归转化为尾递归,从而迭代求出结果。

后两种方法在时空复杂度上均有较大改善,但其适用范围有限。

三、算法编写及算法应用分析题:1.冒泡排序算法的基本运算如下:for i ←1 to n-1 dofor j ←1 to n-i doif a[j]<a[j+1] then交换a[j]、a[j+1];分析该算法的时间复杂性。

解答:排序算法的基本运算步为元素比较,冒泡排序算法的时间复杂性就是求比较次数与n的关系。

1)设比较一次花时间1;2)内循环次数为:n-i次,(i=1,…n),花时间为:3)外循环次数为:n-1,花时间为:2.设计一个分治算法计算一棵二叉树的高度。

《算法设计与分析》递归算法典型例题

《算法设计与分析》递归算法典型例题

算法递归典型例题实验一:递归策略运用练习三、实验项目1运用递归策略设计算法实现下述题目的求解过程。

题目列表如下:(1)运动会开了N天,一共发岀金牌M枚。

第一天发金牌1枚加剩下的七分之一枚,第二天发金牌2枚加剩下的七分之一枚,第3天发金牌3枚加剩下的七分之一枚,以后每天都照此办理。

到了第N天刚好还有金牌N枚,到此金牌全部发完。

编程求(2)国王分财产。

某国王临终前给儿子们分财产。

他把财产分为若干份,然后给第一个儿子一份,再加上剩余财产的1/10;给第二个儿子两份,再加上剩余财产的1/10 ;……;给第i个儿子i份,再加上剩余财产的1/10。

每个儿子都窃窃自喜。

以为得到了父王的偏爱,孰不知国王是“一碗水端平”的。

请用程序回答,老国王共有几个儿子?财产共分成了多少份?源程序:(3)岀售金鱼问题:第一次卖岀全部金鱼的一半加二分之一条金鱼;第二次卖岀乘余金鱼的三分之一加三分之一条金鱼;第三次卖岀剩余金鱼的四分之一加四分之一条金鱼;第四次卖岀剩余金鱼的五分之一加五分之一条金鱼;现在还剩下11条金鱼,在岀售金鱼时不能把金鱼切开或者有任何破损的。

问这鱼缸里原有多少条金鱼?(4)某路公共汽车,总共有八站,从一号站发轩时车上已有n位乘客,到了第二站先下一半乘客,再上来了六位乘客;到了第三站也先下一半乘客,再上来了五位乘客,以后每到一站都先下车上已有的一半乘客,再上来了乘客比前一站少一个……,到了终点站车上还有乘客六人,问发车时车上的乘客有多少?(5)猴子吃桃。

有一群猴子摘来了一批桃子,猴王规定每天只准吃一半加一只(即第二天吃剩下的一半加一只,以此类推) ,第九天正好吃完,问猴子们摘来了多少桃子?(6)小华读书。

第一天读了全书的一半加二页,第二天读了剩下的一半加二页,以后天天如此……,第六天读完了最后的三页,问全书有多少页?(7)日本著名数学游戏专家中村义作教授提岀这样一个问题:父亲将2520个桔子分给六个儿子。

分完后父亲说:“老大将分给你的桔子的1/8给老二;老二拿到后连同原先的桔子分1/7 给老三;老三拿到后连同原先的桔子分1/6给老四;老四拿到后连同原先的桔子分1/5给老五;老五拿到后连同原先的桔子分1/4给老六;老六拿到后连同原先的桔子分1/3给老大”。

递归算法的例子

递归算法的例子

递归算法的例子
1. 计算阶乘不就是个很好的例子嘛!比如计算 5 的阶乘,5! 不就是
5×4×3×2×1 嘛,这就是通过不断用较小的数的阶乘来计算呀,这多有意思啊!
2. 斐波那契数列呀!就像兔子繁殖一样神奇,前两个数相加得到下一个数,是不是很特别?这就是典型的递归算法呀!
3. 走迷宫的时候,你可以用递归算法来试着找路呀!哎呀,要是不这样试试,怎么能找到出口呢?
4. 汉诺塔问题啊,把那些盘子移来移去,不就是递归在发挥作用嘛,神奇吧!
5. 二叉树的遍历,就像是在森林里探索一样,一层一层地深入,这不是递归算法在帮忙嘛!
6. 画分形图形的时候,你看那美丽又复杂的图案,都是递归算法创造出来的呀,哇塞!
7. 分解一个大问题成小问题,再解决小问题,这不就是递归嘛,就像拆礼物一样,一层一层去发现惊喜!
8. 你想想,电脑下棋的时候,不也是用递归算法来分析各种走法吗,真的超厉害的!
总之,递归算法在好多地方都大显身手呢,它让很多复杂的事情变得简单又有趣,能创造出很多神奇的效果呀!。

递归练习题(打印版)

递归练习题(打印版)

递归练习题(打印版)### 递归练习题(打印版)#### 一、递归基础概念题1. 定义题:请简述什么是递归,并给出递归的基本形式。

2. 判断题:以下哪些函数是递归的?- A. `f(x) = x + 1`- B. `g(n) = n * g(n-1)` (n > 0)- C. `h(x) = x * h(x-1)` (x > 1)3. 简答题:递归和迭代有什么区别?#### 二、递归函数编写题1. 编写递归函数:编写一个递归函数,实现阶乘计算。

2. 编写递归函数:编写一个递归函数,实现斐波那契数列的第n项。

3. 编写递归函数:编写一个递归函数,实现汉诺塔问题的解决方案。

#### 三、递归算法应用题1. 应用题:如何使用递归算法解决归并排序问题?2. 应用题:使用递归算法解决二叉树的深度优先搜索(DFS)。

3. 应用题:描述如何使用递归算法实现图的深度优先搜索(DFS)。

#### 四、递归优化题1. 优化题:对于递归算法,如何避免重复计算?2. 优化题:请解释尾递归优化的概念,并给出一个尾递归的例子。

3. 优化题:如何使用记忆化递归(Memoization)来优化递归算法?#### 五、递归问题解决题1. 问题解决题:给定一个数字n,请使用递归算法找出n的二进制表示中1的个数。

2. 问题解决题:使用递归算法实现一个函数,判断一个字符串是否是回文。

3. 问题解决题:给定一个整数数组,使用递归算法找出数组中的最大值。

#### 六、递归思维拓展题1. 思维拓展题:递归算法在解决哪些类型的问题时特别有效?2. 思维拓展题:在编程中,递归算法有哪些潜在的缺点?3. 思维拓展题:请讨论递归算法在人工智能领域的应用。

#### 七、递归实践题1. 实践题:实现一个递归函数,用于计算组合数C(n, k)。

2. 实践题:编写一个递归函数,实现快速排序算法。

3. 实践题:给定一个字符串,使用递归算法实现字符串的反转。

算法设计与分析-递归法

算法设计与分析-递归法

b)
cn k
n1 n1
O (nlog b a ) T (n) O(nk log b n) O(nk )
a bk a bk a bk
但是并非所有的递推式都可以用公式法求解。 例T(n)=2T(n/2)+nlogn 由于a=2, b=2, f(n)=nlogn和nlogba=n。看起来似乎属于 主定理情况(3),但事实上f(n)只是渐近大于n,但并不 是多项式大于n。f(n)与的nlogba比值是log n,对于任何 正数,log n渐近小于n,所以,此例不能运用定理。
1 替换方法
替换方法要求首先猜测递推式的解,然后用归纳法证明。
例2.2 T(n) 2T(n / 2) n
需要注意在上述证明过程中,没有考虑初始条件,而初始条 件是归纳法成立的基础。上例归纳证明的初始条件是是 T(1)≤c,只要选择足够大的c≥1即成立。
2.迭代方法
迭代方法的思想是扩展递推式,将递推式先转换成 一个和式,然后计算该和式,得到渐近复杂度。 例2.4 使用迭代方法分析 T (n) 2T (n / 2) n2
本章要点
• 递归算法特性
• 递推关系 • 递归算法的应用
章节内容
2.1 递归算法 2.1.1 递归算法特性 2.1.2 递归算法的执行过程 2.1.3 递推关系
2.2 递归法应用举例
2.3 典型问题的C++程序
2.4 小结
2.1 递归法
2.1.1 递归算法的特性
若一个算法直接的或间接的调用自己本身,则称这个算 法是递归算法。递归本质上也是一种循环的算法结构,它把较 复杂的计算逐次归结为较简单的情形的计算,直到归结到最简 单情形的计算,并最终得到计算结果为止。

算法设计与分析 第三章1 循环与递归

算法设计与分析 第三章1 循环与递归

3.1.2 递归设计要点
◆递归算法是一个模块(函数、过程)除了可调用 其它模 块(函数、过程)外,还可以直接或间接 地调用自身的算法。 ◆递归是一种比迭代循环更强、更好用的循环结构。 ◆只需要找出递归关系和最小问题的解。 ◆递归方法只需少量的步骤就可描述出解题过程所需 要的多次重复计算,大大地减少了算法的代码量。
main( ) {int i,j,a[100][100],n,k; input(n); k=1; for(i=1;i<=n;i=i+1) for( j=1;j<=n+1-i;j=j+1) {a[i-1+j][j]=k; k=k+1;} for(i=1;i<=n;i=i+1) {print( “换行符”); for( j=1;j<=i;j=j+1) print(a[i][j]); } }
数学模型2:Sn=Sn-1+(-1)n+1An;
An=An-1 *1/((2*n-2)*(2*n-1))
main( ) {int i,n, sign; float s,t=1; input(n); s=1; sign=1; for(i=2;i<=n;i=i+1) {sign=-sign; t= t*(2*i-2)*(2*i-1)}; s=s+ sign/t; } print(“Sum=”,s); }
递归的关键
递归定义:使问题向边界条件转化的规则。递归定 义必须能使问题越来越简单。 递归边界条件:也就是所描述问题的最简单情况, 它本身不再使用递归的定义。
递归算法解题通常有三个步骤:
1)分析问题、寻找递归:找出大规模问题与小规模问 题的关系,这样通过递归使问题的规模逐渐变小。 2)设置边界、控制递归:找出停止条件,即算法可解 的最小规模问题。 3)设计函数、确定参数:和其它算法模块一样设计函 数体中的操作及相关参数。

递归算法典型例题数楼梯

递归算法典型例题数楼梯

递归算法典型例题数楼梯递归算法是计算机科学领域常见且重要的概念之一。

它通过将问题分解为更小的子问题,并使用函数自身来解决这些子问题,从而实现对原始问题的解决。

在本文中,我们将探讨一个经典的递归算法问题:数楼梯。

在这个问题中,我们需要使用递归算法来计算爬n个楼梯的不同方式数量。

假设我们有n个楼梯,每次可以选择爬1个楼梯或2个楼梯。

我们的目标是找出爬到第n个楼梯的所有不同方式的数量。

为了解决这个问题,我们可以使用递归算法。

首先,我们考虑最简单的情况,当n等于0或1时,只有一种方式,即不爬楼梯。

当n等于2时,有两种方式,即爬1个楼梯两次或爬2个楼梯一次。

这些是我们的递归基。

然后,我们可以将问题拆分为更小的子问题。

假设我们已经知道了爬到第n-1个楼梯的方式数量(f(n-1))和爬到第n-2个楼梯的方式数量(f(n-2)),那么我们可以通过以下方式计算爬到第n个楼梯的方式数量:f(n) = f(n-1) + f(n-2)因为我们每次只能选择爬1个或2个楼梯,所以爬到第n个楼梯的方式数量等于爬到第n-1个楼梯方式数量加上爬到第n-2个楼梯方式数量的和。

现在,我们可以编写递归函数来解决这个问题。

以下是一个简单的递归函数来计算爬到第n个楼梯的方式数量:```pythondef count_stairs(n):if n == 0 or n == 1:return 1else:return count_stairs(n-1) + count_stairs(n-2)```在这个递归函数中,我们首先处理递归基的情况。

如果n等于0或1,我们返回1,表示只有一种方式。

否则,我们递归地调用函数count_stairs来计算爬到第n-1个楼梯和第n-2个楼梯的方式数量,并返回它们的和。

然而,上面的递归函数存在一个明显的问题。

当我们计算较大的n时,会出现重复计算的情况。

例如,在计算count_stairs(5)时,我们需要计算count_stairs(4)和count_stairs(3)。

【算法分析】递归算法的几个经典例子

【算法分析】递归算法的几个经典例子

【算法分析】递归算法的⼏个经典例⼦例⼀:整数划分问题 将正整数n表⽰成⼀系列正整数之和:n=n1+n2+…+nk,其中n1≥n2≥…≥nk≥1,k≥1。

正整数n的这种表⽰称为正整数n的划分。

求正整数n的不同划分个数。

例如:正整数6有如下11种不同的划分:6;5+1;4+2,4+1+1;3+3,3+2+1,3+1+1+1;2+2+2,2+2+1+1,2+1+1+1+1;1+1+1+1+1+1在本例中,如果设p(n)为正整数n的划分数,则难以找到递归关系,因此考虑增加⼀个⾃变量:将最⼤加数n1不⼤于m的划分个数记作q(n,m)。

下⾯对可能出现的四种情况进⾏分析:① m=1: 当m等于1时,对n的划分只可能1+1+1+……+1这⼀种情况。

②m>n时: 当m⼤于n时,由于划分中不可能出现负数,所以{n1, n2, n2,… , nk}(n = n1+n2+n3+……+nk)只可能出现⼩于等于n的整数。

故有q(n, m)=q(n, n)⑤m=n时: 当m等于n时,包含n⾃⾝的划分和没有n的划分两个部分。

⽽包含n⾃⾝的划分只有⼀种情况,故有有q(n, n)=1+q(n,n-1)④m<n时: n的m划分有包含m和不包含m两个部分。

其中包含m的部分⽤集合可表⽰为{m, {x1, x2, x3, 4,…, xk}}(其中x1+x2+……+xk=n-m)【详解见图1】,这部分的划分数为q(n-m, m);⽽不包含m的划分中,最⼤值不能为m,故划分数就等于q(n, m)。

所以在m<n时整数n的划分数为:q(n, m)=q(n, m-1)+q(n-m, m)。

【图1:ipad坏了,⼀时找不到纸,后⾯再补吧。

】递归求整数划分:1int q(int n, int m){2if(m==1){3return1;4 }5else if(m>n){6return q(n,n);7 }8else if(m==n){9return q(n,n-1)+1;10 }11else if(m<n){12return q(n-m, m)+q(n,m-1);13 }14 }。

递归算法经典题目

递归算法经典题目

递归算法经典题目递归算法是一种非常强大的编程技术,它能够解决一些复杂的问题,将它们分解为更小的子问题。

以下是一些经典的递归算法题目:1. 斐波那契数列:这是一个经典的递归问题,斐波那契数列中的每个数字都是前两个数字的和。

例如,0, 1, 1, 2, 3, 5, 8, 13, 21... 编写一个函数来计算斐波那契数列中的第n个数字。

2. 阶乘:阶乘是一个数的所有小于及等于该数的正整数的乘积。

例如,5的阶乘(记作5!)是5 4 3 2 1 = 120。

编写一个函数来计算一个数的阶乘。

3. 二分搜索:二分搜索是一种在排序数组中查找特定元素的搜索算法。

编写一个函数,该函数使用二分搜索在给定的排序数组中查找特定的元素。

4. 回溯算法:回溯算法用于解决决策问题,例如八皇后问题。

在这个问题中,我们需要在一个8x8棋盘上放置8个皇后,使得任何两个皇后都不在同一行、同一列或同一对角线上。

编写一个使用回溯算法解决八皇后问题的函数。

5. 合并排序:合并排序是一种分治算法,它将一个大的列表分成两个较小的子列表,对子列表进行排序,然后将它们合并成一个已排序的列表。

编写一个使用递归实现合并排序的函数。

6. 快速排序:快速排序也是一种分治算法,它选择一个"基准"元素,然后将所有比基准小的元素放在其左边,所有比基准大的元素放在其右边。

然后对左右两个子列表进行快速排序。

编写一个使用递归实现快速排序的函数。

7. 深度优先搜索(DFS):这是一种用于遍历或搜索树或图的算法。

这个算法会尽可能深地搜索树的分支。

当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。

这一过程一直进行到已发现从源节点可达的所有节点为止。

如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。

编写一个使用递归实现深度优先搜索的函数。

这些题目都可以帮助你理解和应用递归算法。

leetcode递归例题

leetcode递归例题

leetcode递归例题以下是一篇关于LeetCode 递归例题的介绍:递归是算法设计中一种非常常见和有用的技术,它能够将一个复杂的问题分解成更小的子问题,从而简化问题的解决。

在LeetCode 算法题库中,有许多题目都可以使用递归方法解决。

下面我们将介绍几个经典的递归例题,帮助大家更好地理解递归的原理和应用。

1. 斐波那契数列题目描述:给定一个整数n,返回第n 个斐波那契数。

递归解法:```pythondef fibonacci(n):if n <= 1:return nelse:return fibonacci(n-1) + fibonacci(n-2)```在这个解法中,我们首先判断n 是否小于等于1,如果是,直接返回n。

否则,我们递归地调用fibonacci 函数来计算前两个斐波那契数,然后将它们相加得到第n 个斐波那契数。

需要注意的是,这种递归解法的时间复杂度是指数级的,因为它需要计算很多重复的子问题。

在实际应用中,我们需要考虑使用动态规划等其他方法来优化算法。

2. 反转链表题目描述:给定一个链表的头节点head,将其反转并返回新的头节点。

递归解法:```pythonclass ListNode:def __init__(self, val=0, next=None):self.val = valself.next = nextdef reverseList(head: ListNode) -> ListNode:if not head or not head.next:return headelse:new_head = reverseList(head.next)head.next.next = headhead.next = Nonereturn new_head```在这个解法中,我们首先判断头节点是否为空或者只有一个节点,如果是,直接返回头节点。

否则,我们递归地调用reverseList 函数来反转链表的剩余部分,然后将当前节点设置为反转后链表的头节点。

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

算法递归典型例题实验一:递归策略运用练习三、实验项目1.运用递归策略设计算法实现下述题目的求解过程。

题目列表如下:(1)运动会开了N天,一共发出金牌M枚。

第一天发金牌1枚加剩下的七分之一枚,第二天发金牌2枚加剩下的七分之一枚,第3天发金牌3枚加剩下的七分之一枚,以后每天都照此办理。

到了第N天刚好还有金牌N枚,到此金牌全部发完。

编程求N和M。

(2)国王分财产。

某国王临终前给儿子们分财产。

他把财产分为若干份,然后给第一个儿子一份,再加上剩余财产的1/10;给第二个儿子两份,再加上剩余财产的1/10;……;给第i 个儿子i份,再加上剩余财产的1/10。

每个儿子都窃窃自喜。

以为得到了父王的偏爱,孰不知国王是“一碗水端平”的。

请用程序回答,老国王共有几个儿子?财产共分成了多少份?源程序:(3)出售金鱼问题:第一次卖出全部金鱼的一半加二分之一条金鱼;第二次卖出乘余金鱼的三分之一加三分之一条金鱼;第三次卖出剩余金鱼的四分之一加四分之一条金鱼;第四次卖出剩余金鱼的五分之一加五分之一条金鱼;现在还剩下11条金鱼,在出售金鱼时不能把金鱼切开或者有任何破损的。

问这鱼缸里原有多少条金鱼?(4)某路公共汽车,总共有八站,从一号站发轩时车上已有n位乘客,到了第二站先下一半乘客,再上来了六位乘客;到了第三站也先下一半乘客,再上来了五位乘客,以后每到一站都先下车上已有的一半乘客,再上来了乘客比前一站少一个……,到了终点站车上还有乘客六人,问发车时车上的乘客有多少?(5)猴子吃桃。

有一群猴子摘来了一批桃子,猴王规定每天只准吃一半加一只(即第二天吃剩下的一半加一只,以此类推),第九天正好吃完,问猴子们摘来了多少桃子?(6)小华读书。

第一天读了全书的一半加二页,第二天读了剩下的一半加二页,以后天天如此……,第六天读完了最后的三页,问全书有多少页?(7)日本著名数学游戏专家中村义作教授提出这样一个问题:父亲将2520个桔子分给六个儿子。

分完后父亲说:“老大将分给你的桔子的1/8给老二;老二拿到后连同原先的桔子分1/7给老三;老三拿到后连同原先的桔子分1/6给老四;老四拿到后连同原先的桔子分1/5给老五;老五拿到后连同原先的桔子分1/4给老六;老六拿到后连同原先的桔子分1/3给老大”。

结果大家手中的桔子正好一样多。

问六兄弟原来手中各有多少桔子?四、实验过程(一)题目一:……1.题目分析由已知可得,运动会最后一天剩余的金牌数gold等于运动会举行的天数由此可倒推每一天的金牌剩余数,且每天的金牌数应为6的倍数。

2.算法构造设运动会举行了N天,If(i==N)Gold[i]=N;Else gold[i]=gold[i+1]*7/6+i;3.算法实现#include <iostream> // 预编译命令using namespace std;void main() //主函数{int i=0,count=0; //count表示运动会举办的天数int gold[100]; //定义储存数组do{count=count+6; // 运动会天数加六gold[count]=count;for (i=count-1; i>=1; i--){if (gold[i+1]%6!=0 )break; // 跳出for循环elsegold[i]=gold[i+1]*7/6+i; //计算第i天剩余的金牌数}} while( i>=1 ); // 当i>=1 继续做do循环cout <<"运动会开了"<<count<<"天"<< endl; //返回天数cout<<"总共发了"<<gold[1]<<"枚金牌"<<endl; //返回金牌数}4.运行结果(二)题目二:……1.题目分析由已知可得,最后一个儿子得到的遗产份数即为王子数目,由此可得到每个儿子得到的遗产份数,在对遗产数目进行合理性判断可得到符合要求的结果。

2.算法构造设皇帝有count个王子,property[count]=count;for (i=count-1; i>=1; i--){if (property[i+1]%9!=0 )break; // 数目不符跳出for循环elseproperty[i]=property[i+1]*10/9+i; //计算到第i个王子时剩余份数}3.算法实现#include <iostream> // 预编译命令using namespace std;void main() //主函数{int i=0,count=0; //count表示国王的儿子数int property[100]; //定义储存数组,表示分配到每个王子时剩余份数do{count=count+9; //王子数目为9的倍数property[count]=count;for (i=count-1; i>=1; i--){if (property[i+1]%9!=0 )break; // 数目不符跳出for循环elseproperty[i]=property[i+1]*10/9+i; //计算到第i个王子时剩余份数}} while( i>=1 ); // 当i>=1 继续做do循环cout <<"皇帝有"<<count<<"个儿子"<< endl; //返回王子数cout<<"遗产被分成"<<property[1]<<"份"<<endl; //返回遗产份数}4.运行结果(三)题目三:……1.题目分析由最后一天的金鱼数目,可递推得到每天的金鱼数目,第一天的数目即为金鱼总数。

2.算法构造fish[5]=11;for (i=4; i>=1; i--)fish[i]=(fish[i+1]*(i+1)+1)/i; //计算到第i天剩余金鱼条数3.算法实现#include <iostream> // 预编译命令using namespace std;void main() //主函数{int i=0;int fish[6]; //定义储存数组各天剩余金鱼数fish[5]=11;for (i=4; i>=1; i--)fish[i]=(fish[i+1]*(i+1)+1)/i; //计算到第i天剩余金鱼条数c out<<"浴缸里原有金鱼"<<fish[1]<<"条"<<endl; //返总金鱼数}4.运行结果(四)题目四:……1.题目分析有到终点站时车上的乘客数可求得到任意一站的乘客人数,到第二站时车上的乘客数目即为发车时车上的乘客数。

2.算法构造n um[8]=6; //到终点站车上还有六人f or(i=7; i>=2; i--)num[i]=2*(num[i+1]-8+i); //计算到第i站车上的人数3.算法实现#include <iostream> // 预编译命令using namespace std;void main() //主函数{int i=0;i nt num[9]; //定义储存数组n um[8]=6; //到终点站车上还有六人f or(i=7; i>=2; i--)num[i]=2*(num[i+1]-8+i); //计算到第i站车上的人数c out<<"发车时车上有"<<num[2]<<"位乘客"<<endl; //返总发站人数,即为到第二站时车上人数}4.运行结果(五)题目五:……1.题目分析可假设有第十天,则第十天剩余的桃子数目为0,由此递推可得每一天剩余的桃子数目。

第一天的桃子数目即为猴子摘桃子的总数。

2.算法构造n um[10]=0; //第n天吃前的桃子数f or(i=9; i>=1; i--)3.算法实现num[i]=2*(num[i+1]+1); //计算到第i天剩余的桃子数算法实现#include <iostream> // 预编译命令using namespace std;void main() //主函数{int i=0;i nt num[11]; //定义储存数组n um[10]=0; //第n天吃前的桃子数f or(i=9; i>=1; i--)num[i]=2*(num[i+1]+1); //计算到第i天剩余的桃子数c out<<"猴子共摘来了"<<num[1]<<"个桃子"<<endl; //输出总的桃子数,即第一天吃前的数目}4.运行结果(六)题目六:……1.题目分析由第六天剩余的页数可递推得到每天的剩余页数,第一天的页数即为全书的页数2.算法构造num[6]=3; //到第n天时剩余的页数f or(i=5; i>=1; i--)num[i]=2*(num[i+1]+2); //计算到第i天剩余的页数3.算法实现#include <iostream> // 预编译命令using namespace std;void main() //主函数{int i=0;i nt num[7]; //定义储存数组n um[6]=3; //到第n天时剩余的页数f or(i=5; i>=1; i--)num[i]=2*(num[i+1]+2); //计算到第i天剩余的页数c out<<"全书共有"<<num[1]<<"页"<<endl; //输出总页数,即第一天吃前的数目}4.运行结果(七)题目七:……1.题目分析由已知可得,第一个儿子得到的橘子数目为平均数的一半,由此可得到第一个儿子原先的橘子数目,而第i个儿子原先的橘子数目可由递推公式得到;2.算法构造if(i==0){a[i]=(ave-ave/2)*(8-i)/(8-i-1); //第一个儿子的数目left=a[i]-ave/2;}else{a[i]=ave*(8-i)/(8-i-1)-left; //由left求第i+1个儿子的橘子数目left=ave/(8-i-1); //第i+1个儿子得到的橘子数目}3.算法实现#include<iostream>using namespace std;void main(){i nt a[6]; //存放六个儿子原先手中的橘子数目i nt left=0; //存放下一个儿子得到的橘子数目i nt ave=420;f or(int i=0;i<6;i++){if(i==0){a[i]=(ave-ave/2)*(8-i)/(8-i-1); //第一个儿子的数目left=a[i]-ave/2;}else{a[i]=ave*(8-i)/(8-i-1)-left; //由left求第i+1个儿子的橘子数目left=ave/(8-i-1); //第i+1个儿子得到的橘子数目}}f or(i=0;i<6;i++)cout<<"第"<<i+1<<"个儿子原先手中的的橘子数为"<<a[i]<<endl; //输出每个儿子原先手中的橘子数目}4.运行结果。

相关文档
最新文档