#记录课程学习#
完成以下编程题,要求如下。 1)体会递归问题的两个基本条件。 2)比较递归与显式用栈实现的方法。 3)思考递归编程存在的局限性及解决方法。 4)完成实验报告。 1.编写把十进制正整数转换为S进制(S=2,8,16)数输出的递归算法。 2.编写出计算Fib(n)的递归算法。并分析递归算法和非递归算法它们的时间复杂度和空间复杂度。 3.杨辉三角形的递归实现。 4.一个射击运动员打靶,靶一共有10环,连开10枪打中90环的可能性有多少种?试用递归算法实现。 【《程序员面试宝典》Ch8,电子工业出版社】 分析:本题可以通过10重循环实现,但这样的时间复杂度和空间复杂度无疑很高。比较好的方法是采用递归的方式。程序结果一共有92 378种可能。 5.编写一个递归算法,输出自然数1~n这n个数的全排列 6.编写GRAY码的递归算法。 二、实验环境:(本次实验所需要的平台和相关软件) Visual studio 2022 三、实验内容及步骤:(本次实验计划安排的实验内容和具体实现步骤) 四、实验过程和结果:(记录实验过程和结果、以及所出现的问题和解决方法) 1.十进制正整数转换为S进制: 2.斐波那契数列: 图表 1 递归算法 图表 2 调用栈 递归算法:时间复杂度O(2^n)。每次递归调用会将问题规模减少1或2,而递归树的高度为 n,每个节点的分支数为 2(除了最底层的叶子节点外)。 每一次递归调用都会创建一个新的栈帧来保存函数调用的状态。每个栈帧都包含了局部变量、返回地址以及其他相关信息。在递归调用深度达到n时,会有n个栈帧被同时创建并占用内存。由于栈帧是在堆栈上分配的,因此会占用一定的内存空间。每个栈帧的大小取决于它所包含的变量和参数。对于斐波那契数列的递归算法来说,每个栈帧只需要保存很少的信息,即函数调用的参数和返回值。因此,每个栈帧的大小是固定且很小的。总的内存占用量取决于递归的深度。由于斐波那契数列的递归算法需要递归调用n次,所以在最坏情况下,递归深度是n。即空间复杂度为O(n)。 显式调用栈:时间复杂度O(n),空间复杂度O(n)。 图表 3 记忆化数组 图表 4 迭代实现(非递归) 记忆化数组:时间复杂度为 O(n),空间复杂度为 O(n)。 迭代实现:时间复杂度为 O(n),空间复杂度为 O(1)。 矩阵快速幂 矩阵快速幂算法能将时间复杂度和空间复杂度分别压缩到O(log n),O(1)。 3.杨辉三角: 4. 一个射击运动员打靶,靶一共有10环,连开10枪打中90环的可能性有多少种?试用递归算法实现。 【《程序员面试宝典》Ch8,电子工业出版社】:
采用记忆化数组将运行时间压缩到1秒之内。
图中代码代表了两种方法:第一种的思路是:将存储全排列的数组看成n个空位,往空位里填数据。初始时n个空位,先填第一个空位,第一个空位可以填的数据有三种,每一种往下填第二个空位,第二个空位可以填的数据有两种,以此往下类推。 第二种:将空位先填上123,固定几个数,然后递归交换两个位置上的数据。 K=0表示固定k+1个数,也表示当前正在处理的子数组的起始位置。当k==m即所有的数都已固定时输出数组。 6.Gray码是一个长度为2n 对比来看面对n在30以上的情况,C++的计算时间要比Python少,即效率高于py。 Cnt若为int类型,n=30,cnt=1073741824,即230 将int 改为long long, int可以存储的数据范围在64位系统中是-231 此外还有C++库函数next_permutation 以下为GPT生成的代码 在面对较小数据量时,使用dfs和next_permutation消耗的时间近似。 五、实验中的问题及解决:(本次实验中在编程中碰到的错误等问题及解决方法) 1.安装卸载MathType:安装MathType会使Word等软件在粘贴时发生一些错误,上网查找原因,发现比较麻烦,便卸载MathType采用LaTeX在线网页书写数学公式。此外Word本身也可以插入数学公式。LaTeX无法将2^30转化成230 2.全排列采用交换的代码平时不常用,故较难理解。平时习惯用填空的思路。还要拓展思维,学习更多的算法。 |