Lecture 9

2023-11-05

绪论

这一章节介绍的是divide-and-conquer multiplication,divide的意思是分开,conquer的意思是占据,控制,divide-and-conquer直译下来就是分开后控制,其实就是分而治之的意思,multiplication的意思是乘法。divide-and-conquer multiplication算法的主要核心思想就是分治,通过分治来简化各种较为复杂的乘法运算。

后面还介绍了有关FFT的知识点,因为我也是问了别人才弄懂的,不做过多赘述。


Integer Multiplication

首先讨论实数与实数(整型与整型,浮点型与浮点型)之间的运算:

之前提到过基础的运算加减乘除,左移右移等的复杂度都视作O(1),这个O(1)不是说只做一次操作,而是相对于字节长度固定的整型(浮点型)而言,因为字节长度也就是位数固定,和位数相关的运算的复杂度也看做常数级。

例如加减运算和左移右移运算,如果限定的位数为n,需要依次对每一位进行运算和记录进位,所以复杂度为O(n)

int整型的位数为32,也就是说一次加法运算做的操作次数约为32个常数单位。

在这里插入图片描述
如果是两个二进制数的乘法,需要其中的一个二进制数对另一个二进制数的每一位逐步进行运算,然后将运算的结果进行错位的相加。每一位(乘法)运算的复杂度为O(n),n位的运算的复杂度就为O(n2),错位相加总共需要相加的位数为n*n=n2,根据前面的结论也可以得到复杂度为O(n2),总结n位二进制数相乘的复杂度为O(n2)。

int整型的位数为32,也就是说一次乘法运算做的操作次数约为32*32=1024个常数单位。同样都为基础运算,相较于加减法和左右移位,乘法的复杂度就要高很多。这就是为什么在前面提到的哈希技术中,需要尽可能地将乘法和模运算用左移右移运算来代替。

在这里插入图片描述

上面是一般的二进制乘法,分治思想是考虑将大的问题分割成若干个子问题解决,用分治法来优化二进制乘法就是将n位的二进制数相乘看作一个规模为n的问题,将一个二进制数分割成前半的部分和后半的部分,前半和后半的部分分别进行计算,规模为n的问题不断地切割成若干个规模为n/2的问题。

在这里插入图片描述

伪代码和对应部分的时间复杂度如下:

在这里插入图片描述

子问题复杂度之间的递归关系可以通过代码得到。
在这里插入图片描述
这种表达式对应着分治递归问题的递归树,其中子问题为它所在的大问题的子节点,有一般的情况如下。

在这里插入图片描述
a是需要解决的子问题的种类数,b是分割下来的子问题规模与原问题规模的比例,a和b的值有可能存在一定的关系,也有可能没有,因为分割出来的子问题可能是一样的,不需要重复计算(也有可能子问题都不相同)。

f(n)是分割和合并子问题时操作需要的时间复杂度。

在这里插入图片描述

对于一般的递归分治算法子问题复杂度之间的递归关系式,可以推出规模为n的问题的时间复杂度。

在这里插入图片描述

这样可以推出用分治尝试优化的实数乘法的时间复杂度仍为O(n2),没有能够做到真正意义上时间上的优化。

更好的做法是通过数学的转化将子问题的种类数减少,像下面这种就是减少到了ac,bd,(a-b)(c-d)3种。

在这里插入图片描述

伪代码和对应部分的时间复杂度如下:

在这里插入图片描述

这样的时间复杂度可以从n2优化到n1.585

在这里插入图片描述


Matrix Multiplication

分治乘法主要运用在矩阵与矩阵之间的乘法,普通无优化的矩阵乘法的复杂度为O(n3)。

在这里插入图片描述

用分治法优化矩阵乘法就是将当前n*n规模的矩阵分割成4个规模为(n/2)*(n/2)的子矩阵分别进行运算。这个方法在线代里面叫做分块矩阵,除了可以按照2*2进行分割,也可以按照1*4的方式进行分割。

像下面这样用最简单的方式直接分割,时间复杂度也是不会有多少变化的(线代里面对分块矩阵就是这么使用的,当时老师和慕课认为分块矩阵可以在矩阵存在局部0的情况时加快乘法的效率)。

在这里插入图片描述

更好的情况是像下面一样减少到七种不同的子问题。

在这里插入图片描述
代码和对应部分的时间复杂度如下:

在这里插入图片描述
这样时间复杂度可以优化到O(n2.8)左右,如果边长不能满足一直切割下去的条件就对周围的元素位置进行“补0”。

在这里插入图片描述

这个算法被称为Strassen’s algorithm(斯塔拉森矩阵乘法),当数据很大时,时间复杂度可以降低非常多(n≥2048时,优化过的矩阵乘法的耗时为优化之前的矩阵乘法耗时的1/8)。

矩阵乘法的时间复杂度仍然在不断地向下优化中·······

在这里插入图片描述


Convolution and FFT

Convolution and FFT这部分介绍了一个更为具体和完整的例子。这个例子我问了一下物联学过相关知识的大佬和给我课件的那位旁友然后反复研究了几遍的课件得到的结论就是:

FFT这个算法是用在信号处理,多项式相乘和卷积(convolution)等一系列需要快速将若干个值x1,x2······xn通过多项式转化成y1,y2·······yn的情况。然后我们这章主要介绍的是分治是FFT算法的主要核心算法思想,但是FFT算法你光用分治和上面一样处理是行不通的,或者说只能将原本n3的复杂度优化到n的2.3左右,FFT算法还需要另外的高数方面的知识点(高数82飘过)。

这里只介绍多项式的乘法。

Polynomials multiplication

对于多项式,有相加,相乘和对于某个x值求多项式值的几种操作,对于某个x值求多项式值的方法在前面介绍过,这个方法被称为Horner方法。

你像这样单纯的相乘复杂度就是O(n2)。

在这里插入图片描述

然后我们知道,对于一个n次的多项式,代入n个值可以得到n个结果。如果将系数看作未知数,那么这n个结果和代入的n个值可以像多元方程求解一样将n个系数反过来求出。

于是可以用n个代入的值和多项式值组成的数对来表示n次的多项式。

在这里插入图片描述

这种表达方法称为point-value表达法,比起系数的表达法,在乘法方面的效率要高很多。

在这里插入图片描述
考虑的做法是先将系数表达法转化成point-value表达法,再用point-value表达法进行乘法的运算,将运算后的结果转化回系数表达法。

在这里插入图片描述
因为有FFT算法能够快速地完成两种表达法的转化,所以采用这种两次转化的做法。

如果采用暴力将系数表达法转化成point-value表达法,第一种做法就是使用n次Horner方法,复杂度为n2,两次转化的复杂度不会优于系数表达法直接相乘的复杂度,并且Horner方法只能从系数表达法转化到point-value表达法,不能转化回来(大概)。

第二种方法是如果x幂次的值已知,考虑用线代矩阵相乘的方法来做,但这么做即使按照前面对矩阵的乘法进行优化,复杂度仍然会达到O(n2.38)。

在这里插入图片描述

FFT

FFT算法的核心思想也是分治,分割的方式是按照项次数的奇偶分割出两个最大次数为原多项式一半的多项式。

FFT算法另外最为重要的一个基础定理是欧拉恒等式,代入的n个值分别为欧拉恒等式的n个解,欧拉恒等式解与解之间的的性质,保证了子问题能够逐渐合并到最终的结果且不会出现无用的多项式值(具体为什么将divide和combine那里代入计算一下就明白了)。

在这里插入图片描述

伪代码和各个部分的复杂度如下。

在这里插入图片描述

上面的流程将前后相关的数据连线,不同的操作用不同的颜色表示,可以得到(比较)著名的FFT Butterfly(就学过的朋友所说,按照这个图形记忆反而记不住hhh)。

在这里插入图片描述


总结

这一章是数据结构课本上完全没有的东西,感觉学到了很多没有学过的东西,另外就是四门数学(高数,线代,离散,概率论)真的非常非常重要,不然就会像我一样在FFT算法卡上非常久的时间。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Lecture 9 的相关文章

随机推荐

  • 数据结构和算法(栈的模拟、前中后缀表达式、表达式求值步骤和思路)

    1 栈的介绍 栈的英文为 stack 栈是一个先入后出 FILO First In Last Out 的有序列表 栈 stack 是限制线性表中元素的插入和删除只能在线性表的同一端进行的一种特殊线性表 允许插入和删除的一端 为变化的一端 称
  • qt中qwt的安装的方式

    参考大神博客 https blog csdn net imkelt article details 51234230 utm medium distribute pc relevant none task blog BlogCommendF
  • Error in nextTick “TypeError Cannot read property ‘xxx‘ of undefined“

    报这个错主要是因为子组件还没加载完成就对子组件进行赋值 推荐使用第一个 this nextTick gt 修改子组件的内容 或 setTimeout gt 修改子组件的内容 50 父组件传值给子组件 子组件不能直接修改 会报错 子组件修改父
  • JavaScript中的endsWith

    如何在JavaScript中检查字符串是否以特定字符结尾 示例 我有一个字符串 var str mystring 我想知道该字符串是否以 结尾 我该如何检查 JavaScript中是否有endsWith 方法 我有一个解决方案是获取字符串的
  • 嘴说手画一文搞懂Spark的Join

    Spark Sql的Join和关系型数据库Sql的Join有很多相同点 比如inner join left join right join full join 这是二者都有的概念 并且含义相同 但是 Spark Sql是分布式执行 面对的是
  • ADB命令开启和关闭飞行模式,两段式操作方式!!!!

    开启飞行模式 必须要先执行1 再执行2 执行1 adb shell settings put global airplane mode on 1 执行2 adb shell am broadcast a android intent act
  • Docker部署Elasticsearch集群

    编写docker compose yml version 3 7 services es01 image elasticsearch 7 10 1 container name es01 ports 9200 9200 9300 9300
  • dc-1 靶机渗透学习

    环境 Vmware 虚拟机软件 dc 1 靶机ip地址 192 168 202 130 kali攻击机ip地址 192 168 202 129 本次渗透过程kali攻击机和dc靶机都采取NAT模式 信息收集 首先用ipconfig查看当前k
  • 初始化k8s踩过的坑

    问题一 error execution phase preflight couldn t validate the identity of the API Server abort connecting 这个问题网上有很多的解决方法 大致有
  • 【OpenCV】分离多通道图像RGB的值

    原文地址 http blog csdn net xiaowei cqu article details 7558657 1 计算图像ROI区域RGB的平均值 cvAvg函数 2 通道分离 合并的时候要特别的注意 分离之后的图像时单通道的灰度
  • RabbitMQ:使用Java进行操作

    使用Java操作消息队列 现在我们来看看如何通过Java连接到RabbitMQ服务器并使用消息队列进行消息发送 这里一起讲解 包括Java基础版本和SpringBoot版本 首先我们使用最基本的Java客户端连接方式
  • shell脚本的发送消息

    我们可以利用 Linux 自带的 mesg 和 write 工具 向其它用户发送消息 需求 实现一个向某个用户快速发送消息的脚本 输入用户名作为第一个参数 后面直 接跟要发送的消息 脚本需要检测用户是否登录在系统中 是否打开消息功能 以及当
  • 基于 LLM 的知识图谱另类实践

    本文整理自社区用户陈卓见在 夜谈 LLM 主题分享上的演讲 主要包括以下内容 利用大模型构建知识图谱 利用大模型操作结构化数据 利用大模型使用工具 利用大模型构建知识图谱 上图是之前 我基于大语言模型构建知识图谱的成品图 主要是将金融相关的
  • Go交叉编译

    交叉编译是指在一个硬件平台生成另一个硬件平台的可执行文件 而Go提供了非常方便的交叉编译方式 如何编译 Go交叉编译 涉及到几个环境变量的设置 GOARCH GOOS和CGO ENABLED GOARCH 编译目标平台的硬件体系架构 amd
  • 单元测试框架-Junit

    JUnit作为Java单元测试中的首选框架 在Java开发中使用最为广泛 JUnit 在测试驱动的开发方面有很重要的发展 教程 jUnit 教程 w3cschool BeforeAll修饰的 可以作为整个Class的初始化操作 前置操作 J
  • IDEA的run maven方式启动

    安装jetty插件 1 找到Plugins 查找jetty插件 安装 IDEA Jetty Runner 安装好后重启IDEA 安装插件 Maven Helper 方法同Jetty pom xml添加
  • cocos笔记——如何读取json表

    创建json表 1 将所需数据录入excel表格 或其他可转换为json表的文档 2 复制表中需要的文字 用在线json表转换工具 如 在线json校验格式化工具 中的Excel转json功能 将表格转化为json表的格式 3 复制转化好的
  • Chrome/Edge/Firefox浏览器离线安装包下载地址总汇

    Google Chrome谷歌浏览器离完整离线安装包下载地址整理总汇 每次重装系统 都要为安装 Chrome 而烦恼 虽然现在可以直接从谷歌浏览器官网下载在线安装包进行安装 但是在线安装包安装的版本不可控 大概率是 x86 版本 而且在断网
  • maven切换镜像源

    今天像往常一样准备构建项目时报错 原因是中央仓库暂停更新 导致很多jar包都没有 1 打开settings xml文件 settings xml文件一般在maven的安装目录conf文件夹下 2 切换镜像源 定位到
  • Lecture 9

    绪论 这一章节介绍的是divide and conquer multiplication divide的意思是分开 conquer的意思是占据 控制 divide and conquer直译下来就是分开后控制 其实就是分而治之的意思 mul