计硕3班-陈陇刚-2022222278-第二章 递归与分治策略 作业

news2024/12/23 10:17:22

目录

1. 概括第二章学习内容,总结第二章学习心得

1.1 递归

1.1.1 递归的定义

1.1.2 递归的使用场景

1.2 分治

 1.2.1 分治的定义

1.2.2 分治法使用场景

1.3 学习心得

2. 描述Fibonacci数列递归算法,并进行时间复杂度分析

2.1 Fibonacci数列定义

2.2 递归算法实现

2.2.1 时间复杂度分析

2.3 非递归算法实现

2.3.2 时间复杂度分析

3. 请设计算法,输入适当整数n,计算前n个数的全排列,对算法

进行时间复杂度分析;简要总结算法实验心得

3.1 核心思想

3.2 算法实现

3.3 结果分析

3.4 时间复杂度分析

4. 简要总结Karatsuba’s 大整数乘法、Strassen矩阵乘法的分治策略应用特点

4.1 Karatsuba’s 大整数乘法的分治策略应用特点

4.2 Strassen矩阵乘法的分治策略应用特点

5. 证明二分搜索算法的时间复杂度为O(logn)

6. 结合分治策略思想,讨论归并排序、快速排序的异同

6.1 归并排序算法

6.2 快速排序算法

6.3 总结


1. 概括第二章学习内容,总结第二章学习心得

1.1 递归

1.1.1 递归的定义

        递归是一种解决问题的有效方法,在递归过程中,函数将自身作为子例程调用。递归的思想是把一个大型复杂问题层层转化为一个与原问题规模更小的问题,问题被拆解成子问题后,递归调用继续进行,直到子问题无需进一步递归就可以解决的地步为止

1.1.2 递归的使用场景

1. 当问题和子问题具有递推关系,比如杨辉三角、计算阶乘。

2. 具有递归性质的数据结构,比如链表、树、图。

3. 反向性问题,比如取反。

1.2 分治

 1.2.1 分治的定义

        分治法,字面意思是“分而治之”,就是把一个复杂的1问题分成两个或多个相同或相似的子问题,再把子问题分成更小的子问题直到最后子问题可以简单地直接求解,原问题的解即子问题的解的合并,这个思想是很多高效算法的基础,例如排序算法(快速排序,归并排序),傅里叶变换(快速傅里叶变换)等。

        分治法的基本思想:将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。

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

1.2.2 分治法使用场景

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

1.3 学习心得

        递归是一种编程技巧,一种解决问题的思维方式;分治算法和动态规划很大程度上是递归思想基础上的。递归的基本思想是某个函数直接或者间接地调用自身,这样就把原问题的求解转换为许多性质相同但是规模更小的子问题。我们只需要关注如何把原问题划分成符合条件的子问题,而不需要去研究这个子问题是如何被解决的。分治法的基本思想:将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同。递归地解这些问题,然后将各个子问题的解合并成原问题的解。

2. 描述Fibonacci数列递归算法,并进行时间复杂度分析

        斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……

        在数学上,斐波纳契数列以如下递归的方法定义:

                                        F(0)=0,F(1)=1, F(n)=F(n-1)+F(n-2)(n>=2,n∈N*)。

2.1 Fibonacci数列定义

2.2 递归算法实现

def Fibonnacci(n):
    if (n == 0):
        return 0
    elif (n == 1):
        return 1
    return Fibonnacci(n-1) + Fibonnacci(n-2)

Fibonnacci(9)

2.2.1 时间复杂度分析

        第n层节点个数:2^n 个
        前n层节点个数:1+2+4+……+2^n = (2 ^ n) - 1

        推理:F(n) 有 n-2层
        则F(n)一共有节点数 (2 ^ (n-2)) - 1 = ((2 ^n)/4)-1
        计算时间复杂度规则:不看常数,不看系数,只看最高次数项
        因此:O(F(n)) = O(2 ^n)

2.3 非递归算法实现

def Fibonnacci(n):
    front = 0
    follow = 1
    result = 0
    
    if (n==0 or n==1):
        if(n==0):
            return front
        return follow
    while (n>=2):
        n = n-1
        result = front + follow
        front = follow
        follow = result
    return result

Fibonnacci(9)

2.3.2 时间复杂度分析

        只关注while循环里面的次数,程序从n到2即为时间复杂度O(n-2) + O(2) = O(n)。

3. 请设计算法,输入适当整数n,计算前n个数的全排列,对算法

进行时间复杂度分析;简要总结算法实验心得

3.1 核心思想

        将查找一个全排列的过程看成是一棵N(N表示list的长度)叉树的深度优先遍历。当到达最大深度时候就往后退一步(相当于回溯一步)。

        每次取一个元素之后,就可以进行递归。每个元素都可以当成树的根节点。

        利用一个list来对数据进行存储。

3.2 算法实现

class FullPermutation(object):
    """
    无重复元素的全排列
    """
    def get_full_resolution(self, store, temp_list, test_list):
        # 递归停止条件
        # temp_list用来存储一种完整的全排列
        # 如果长度已经和原始的输入test_list相等,则将这一种全排列存储下来
        # 继续找下一种全排列
        if len(temp_list) == len(test_list):
            store.append(temp_list[:])
        else:
            # 遍历原始输入中的元素,每次取出一个元素
            for i in test_list:
                if i in temp_list:
                    continue
                # 如果当前遍历到的点不在temp_list中
                # 则添加到该列表中
                temp_list.append(i)
                # 添加完一个点之后,剩下的过程其实可以看成同样的过程
                self.get_full_resolution(store, temp_list, test_list)
                # 当找到一种全排列之后,就删掉一个点(往后退一步),继续判断其它的情况
                temp_list.pop()

    def backtrack(self, test_list):
        store = []
        temp_list = []
        self.get_full_resolution(store, temp_list, test_list)
        return store


if __name__ == '__main__':
    test_list = [1, 2, 3, 4]
    c = FullPermutation()
    result = c.backtrack(test_list)
    for i in result:
        print(i)
    print('总共{}种全排列'.format(len(result)))

3.3 结果分析

[1, 2, 3, 4]
[1, 2, 4, 3]
[1, 3, 2, 4]
[1, 3, 4, 2]
[1, 4, 2, 3]
[1, 4, 3, 2]
[2, 1, 3, 4]
[2, 1, 4, 3]
[2, 3, 1, 4]
[2, 3, 4, 1]
[2, 4, 1, 3]
[2, 4, 3, 1]
[3, 1, 2, 4]
[3, 1, 4, 2]
[3, 2, 1, 4]
[3, 2, 4, 1]
[3, 4, 1, 2]
[3, 4, 2, 1]
[4, 1, 2, 3]
[4, 1, 3, 2]
[4, 2, 1, 3]
[4, 2, 3, 1]
[4, 3, 1, 2]
[4, 3, 2, 1]
总共24种全排列

3.4 时间复杂度分析

 # 遍历原始输入中的元素,每次取出一个元素
            for i in test_list:
                if i in temp_list:
                    continue
                # 如果当前遍历到的点不在temp_list中
                # 则添加到该列表中
                temp_list.append(i)
                # 添加完一个点之后,剩下的过程其实可以看成同样的过程
                self.get_full_resolution(store, temp_list, test_list)
                # 当找到一种全排列之后,就删掉一个点(往后退一步),继续判断其它的情况
                temp_list.pop()

        通过观察程序段核心代码for循环语句可知,只有一重循环,且test_list 的长度为n,故时间复杂度为O(n)。 

4. 简要总结Karatsuba’s 大整数乘法、Strassen矩阵乘法的分治策略应用特点

4.1 Karatsuba’s 大整数乘法的分治策略应用特点

        Karatsuba乘法是一种快速乘法。用于数字比较大,相乘的结果超出了基本类型的表示范围,所以不能够直接做乘法运算的运算。此算法主要用于两个大数相乘。普通乘法的复杂度是n2,而Karatsuba算法的复杂度仅为3nlog3。

4.2 Strassen矩阵乘法的分治策略应用特点

        Strassen算法只有在对于维数比较大的矩阵 (N>300) ,性能上才有很大的优势,可以减少很多乘法计算。Strassen算法证明了矩阵乘法存在时间复杂度低于 Θ(N3) 的算法的存在。

5. 证明二分搜索算法的时间复杂度为O(logn)

        我们都知道二分查找在最坏的情况下依次是n/2,n/4,n/8。。。。 一直到1为止。我们假设需要循环x次才能查找到目标数,根据观察二分查找满足如下等式:

n*(1/2)**x = 1

        经过运算得:

2**x = n

         左右两边同时取log以2为底的对数则有:

log2(n) = x

         去掉对数函数的底数,则可以得到二分搜索算法的实际复杂度为:

O(log(n))

6. 结合分治策略思想,讨论归并排序、快速排序的异同

6.1 归并排序算法

        归并排序的核心思想其实很简单,如果要排序一个数组,我们先把数组从中间分成前后两部分,然后分别对前后两部分进行排序,再将排好序的两部分数据合并在一起就可以了。

        归并排序使用的是分治思想,分治也即是分而治之,将一个大问题分解为小的子问题来解决。分治算法一般都是用递归来实现的。分治是一种解决问题的处理思想,递归是一种编程技巧。

        归并排序是一个稳定的排序算法,在进行子数组合并的时候,我们可以设置当元素大小相等时,先将前半部分的数据放入临时数组,这样就可以保证相等元素在排序后依然保持原来的顺序。

        不仅递归求解的问题可以写成递推公式,递归代码的时间复杂度也可以写成递归公式。

        如果我们对 n 个元素进行归并排序所需要的时间是 T(n),那分解成两个子数组排序的时间都是 T(n/2),而合并两个子数组的时间复杂度为 O(n)。所以,归并排序的时间复杂度计算公式为:

                                                         T(1)=C

                                                        T(n)=2∗T(n2)+n,n>1

 

用大 O 标记法来表示,归并排序的时间复杂度为 O(nlogn)。

        从我们的分析可以看出,归并排序的执行效率与原始数据的有序程度无关,其时间复杂度是非常稳定的,不管是最好情况、最坏情况,还是平均情况,时间复杂度都是 O(nlogn)。

        归并排序有一个缺点,那就是它不是原地排序算法。在进行子数组合并的时候,我们需要临时申请一个数组来暂时存放排好序的数据。因为这个临时空间是可以重复利用的,因此归并排序的空间复杂度为 O(n),最多需要存放 n 个数据。

6.2 快速排序算法

        快速排序的思想是,如果要对数组区间 [p, r] 的数据进行排序,我们先选择其中任意一个数据作为 pivot(分支点),一般为区间最后一个元素。然后遍历数组,将小于 pivot 的数据放到左边,将大于 pivot 的数据放到右边。接着,我们再递归对左右两边的数据进行排序,直到区间缩小为 1 ,说明所有的数据都排好了序。

        归并排序是由下向上的,先处理子数组然后再合并。而快速排序正好相反,它的过程是由上向下的,先分出两个子区间,再对子区间进行排序。归并排序是稳定的时间复杂度为 O(n),但它是非原地算法,而快排则是原地排序算法。

        如果快速排序每次都将数据分成相等的两部分,则快排的时间复杂度和归并排序相同,也是 O(nlogn),但这种情况是很难实现的。如果数据原来已经是有序的,则每次的分区都是不均等的,我们需要进行 n 次分区才能完成整个排序,此时快排的时间复杂度就退化成了 O(n2)。

        平均时间复杂度的求解也可以通过递归树来分析,这个问题留待我们以后再解决。我们现在只需要知道,在大部分情况下,快速排序的时间复杂度都可以做到 O(nlogn),只有在极端情况下,才会退化成 O(n2)。

        快速排序是一个原地排序算法,是一个不稳定的排序算法,因为其在数据交换过程中可能会改变相等元素的原始位置。

6.3 总结

        归并排序和快速排序都是利用分治的思想,代码都通过递归来实现,过程非常相似。

        归并排序非常稳定,时间复杂度始终都是 O(nlogn),但不是原地排序;快速排序虽然最坏情况下时间复杂度为 O(n2),但平均情况下时间复杂度为 O(nlogn),最坏情况发生的概率也比较小,而且是原地排序算法,因此应用得更加广泛。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/32362.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

测试人经验谈:需求不明确也能写出测试用例

测试人员的用例编写,一般基于经验和需求文档进行,但是很多时候项目是没有需求的,特别是领导的某个概念提出,然后开发会根据自己的理解完成,测试人员在没有获得任何依据和需求的情况下如何编写测试用例呢? …

【数据结构】七种排序方法,一篇文章掌握

文章目录前言1. 直接插入排序1.1 画图演示1.2 直接插入排序详细步骤1.3 时间复杂度,空间复杂度分析2. 希尔排序2.1 具体步骤描述2.2 代码详解2.3时间复杂度,空间复杂度分析3. 选择排序3.1 画图讲解3.2 代码讲解3.3 时间复杂度,空间复杂度分析4. 快速排序4.1 画图演示…

【C++初阶7-string】真方便,真舒服

前言 本期浅学一下STL的stirng。 内容概览: STLstring 是什么为什么怎么用(接口介绍及使用) 博主水平有限,不足之处望请斧正! 先导 STL C中非常重要的一个东西,STL(Standard Template Library) 标准…

详解华夏银行iDo平台一体化运维的落地过程

随着数字化转型的深入,基于中台和PaaS架构的一体化运维建设也在各行各业快速展开,但是如何将运维平台本身的能力与企业已有的工具能力进行中台化整合、工具场景如何联动,是个复杂而庞大的工程。 本次,史春志老师以华夏银行运维平…

【Revit二次开发】元素(Element)

图元与图元类型元素元素 元素(Element)也称图元 图元作为revit建模的基础,数量庞大,关系千丝万缕。先了解图元的分类,将会帮助我们整理思路,找到功能开发的关键点。 每一个人都可以按照自己的思路将图元进行分类。建模人员可以按…

vue详细教程

原文链接:https://www.cnblogs.com/MrFlySand/p/16921017.html 02vue的安装 程序说明 1、在body中有2个counter,一个是id,一个是class。 2、创建应用,分别用id和class将配置对象传入 语法:Vue.createApp(方法名).mount…

DPDK之PMD原理

PMD是Poll Mode Driver的缩写,即基于用户态的轮询机制的驱动。本文将介绍PMD的基本原理。 在不考虑vfio的情况下,PMD的结构图如下: 图1. PMD结构图 虽然PMD是在用户态实现设备驱动,但还是依赖于内核提供的策略。其中uio模块&…

Java 面试题 —— TCP 粘包、拆包问题

Java 面试题 —— TCP 粘包、拆包问题 1、粘包、拆包问题概况 正常情况: ​  服务端一共接收到客户端的两个数据包,两个数据包各自包含完整的消息。 粘包问题: ​  服务端一共接收到客户端的一个数据包,这个数据包共包含两条…

【java进阶06:数组】使用一维数组模拟栈数据结构 使用二维数组模拟酒店,酒店管理系统 Arrays工具类 冒泡排序算法、选择排序算法、二分法

目录 数组 二维数组 总结 作业 Arrays工具类 数组 数组总结 及 静态初始化一维数组 /* Array:1、java语言中的数组是一种引用数据类型,不属于基本数据类型,数组的父类是Object2、数组实际上是一个容器,可以同时容纳多个元素&#xff08…

【负荷预测、电价预测】基于神经网络的负荷预测和价格预测(Matlab代码实现)

👨‍🎓个人主页:研学社的博客 💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜…

Webpack DevServerExpress 中间件

前言 webpack-dev-server 底层是 express webpack-dev-middleware。 express是基础。 webpack-dev-middleware是中间件,以监听模式启动 webpack,将编译后的文件输出到内存(使用fs-memory),沟通webpack的HRM&#xf…

机器学习之特征提取

Question Orientied:来自论文的一个学习点 Feature extraction 定义: 特征提取是指使用计算机提取图像中属于特征性的信息的方法及过程。 简言之 提取图像关键信息。 特征提取出来的结果叫特征向量。 进入主题之前 普及几个常识: 像素的英文名称:Pixe…

Flutter 完全手册

小册介绍 Flutter 作为一个跨平台的框架,其开发技术栈融合了 Native 和前端的技术,不仅涉及到了 Native(Android、iOS )的开发知识,又吸取了很多前端(例如 React)的技术理念和框架,并…

甘露糖-聚乙二醇-CY3 Cy3-PEG-mannose

甘露糖-聚乙二醇-CY3 Cy3-PEG-mannose 中文名称:甘露糖-荧光染料CY3 英文名称:mannose-Cyanine3 别称:CY3标记甘露糖,CY3-甘露糖 溶解性:溶于大部分有机溶剂,如:DCM、DMF、DMSO、THF等等。在…

业务数据分析-Excel数据透视表(四)

目录 1、什么是数据透视表 2、如何操作 3、数据透视表的优势 4、适用什么场景 5、使用前注意事项 1、什么是数据透视表 先来举个例子 看下面这段对话 下午5点30 boss:把这张表给我整理成如下格式,就是根据平台给我汇总一下销量和收入&#xff0c…

机械工程基础笔记整理

第一章 绪论 第一节 课程的特点 1. 综合性 本课结合了工程力学,机械工程材料,常用机构,支撑零部件,机械传动,液压传动,气压传动的相关知识。 2. 基础性 无论从事机械制造,还是使用研究机械&…

OpenCV图像处理——(实战)答题卡识别试卷

总目录 图像处理总目录←点击这里 二十、答题卡识别试卷 20.1、预处理 灰度图 输出灰度图高斯滤波去噪 gray cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) blurred cv2.GaussianBlur(gray, (5, 5), 0)边缘检测 edged cv2.Canny(blurred, 75, 200)20.2、轮廓检测 找到原…

快速构建一个简单的对话+问答AI (上)

文章目录前言part0 资源准备基本功能语料停用词问答闲聊语料获取part01句的表达表达one-hot编码词嵌入大致原理实现简单版复杂版如何训练转换后的形状part02 循环神经网络RNNRNN投影图RNN是三维立体的LSTM&GRUpart03意图识别分词FastText分类FastText网络结构优化点构造Fas…

http请求走私漏洞原理,利用,检测,防护

目录 什么是请求走私 漏洞成因与常见类型 Keep-Alive&Pipeline CL&TE 常见走私类型 1.CL不为0 2.CL CL 3.CL TE 4.TE CL 5.TE TE 走私攻击应用实例(漏洞利用) 使用CL TE走私获取其他用户的请求、Cookie 2.泄露请求头重写请求实现未…

UE4贴图自适应屏幕大小

游戏开发中,不同屏幕下的分辨率不同,模型/物品被拉伸之后贴图也会随之拉伸。 如果需要在不同屏幕下面实现贴图真实大小不变(以下简称为自适应),需要对UV进行缩放处理之后再取得对应贴图的颜色。 本文提供一种能够实现不…