算法设计与分析:分治思想(4)- 快速傅立叶变换(对数组的归约)
本文参考UCAS卜东波老师的计算机算法设计与分析课程撰写
前言
本文主要讲述分治思想在快速傅立叶变换(FFT)中的应用。快速傅立叶变换本质上属于多项式求值,将输入的n个复数变换成n个复数。
快速傅立叶变换(FFT)
问题描述与分析
-
给定n个复数的数组,求在n个特定点的值,其中,表n次单位复根
将上述问题写成结果如下:
考虑最简单的办法,对一个需要用一次for循环(包含n-1次加法和乘法),n个则复杂度为,在分治思想(3)- 平面最近点对寻找问题(对点集归约)一文中也提到过,在遇到n数据规模较大时就力不从心了,因此能否考虑通过分治来降低复杂度。
解决思路
首先观察多项式能进行分治的前提,对单位复根敏感的童鞋应该很容易知道其必然会周期性变化,这里有几个值需要知道(依据复数的三角和指数形式对应即可),所以有,可以发现上述多项式中有很多重复计算的地方,为了更明显的感受,我们举几个简单的例子。
-
当n=4时
可以发现红色区域的内容相同,蓝色区域的内容相差一个
因此我们只需要计算一半的内容即可。由于加法次数多于乘法,因此复杂度只需考虑加法使用的次数,本次计算耗时: -
当n=8时
同样对于n=8的情景是类似的,由于数量过于庞大,这里沿用卜老师的图片
其中,红色区域完全一样,蓝色区域差,再进一步我们可以发现红色区域其实就类似于n=4的情况,其左上与左下相同,右上与右下差,最终可以得到如下图(该图展示了整个分治计算的过程)其中,绿色区域覆盖全部,表示开始需要计算的内容,棕色区域只包含了上半部分的两块内容,在得到棕色区域结果后可以顺势得到下半部分的绿色区域,橙色区域包含上面1/4部分的两块区域,红色区域则值包含最上面一行的两块区域。 绿(要求)->棕(要求)->橙(要求)->红(解)->橙(解)->棕(解)->绿(解),这是一个很明显的递归过程。
-
算法复杂度
这个算法复杂度的计算也很容易,我们在每次划分的时候按照下标的奇偶性将数组分成两份,如n=8时,第一次递归,一组,一组,再进一步递归,一组,一组…而在计算得到各组的结果后将其线性求和(奇数部分要乘上系数),所用时间复杂度为(即中间的加法操作),因此有
将上述过程转换为伪代码如下(由于伪代码中用到数学符号较多,因此借用书本内容)
逆快速傅立叶变换
所谓逆快速傅立叶变换,即傅立叶变换的反过程,即已知,求,值得一提的是,FFT解决的是求值的问题(给定系数,求多项式的值),IFFT解决的是插值问题(给定多项式的值,求系数),将两者写成矩阵形式对比如下:
-
FFT
-
IFFT
本身是一个求逆的过程,由于范德蒙矩阵的特性,得到结果如下,
由此在原始伪代码基础上只需做些许变动即可,如下:
总结
这部分的内容主要阐述了分治思想在多项式计算上的应用,之所以能够分治,是因为我们发现了多项式计算中的冗余部分,这些重复计算内容可以被省略,且多项式的值可以被划分为奇偶两部分的特殊和,那么就可以递归地进行奇偶划分,由此使得计算的复杂度得到了降低。
这里总结一下依据该例得出的分治经验:
- 先使用最直白的办法(通常复杂度是或以上)
- 找出算法计算的冗余部分(这一点很重要,如果没有发现冗余直接划分无法将计算的复杂度往下降)
- 找出可以递归的入口(能够不断迭代往下进行),在多项式计算中是按照奇偶性进行递归
- 考虑合并子问题解的额外开销,如果额外开销过大,则不适宜如此划分