多项式相乘最容易想到的方法就是采用2个for循环,依次遍历相乘累加即可。但时间复杂度为O(n2)。那么是否可用其他的方法来降低遍历比较的次数呢?可用分治法来进行对应切分,然后相乘,再相加。但是这好像并不能减少遍历的次数,因为与之前的合并排序不同的是,合并排序中,如果左边的数若比右边的数小,则左边的左边就不需要与右边的所有数进行比较,因为数是sorted,所以默认比右边的小,无需再比较;而两个多项式相乘,不存在排序,而且每个数都必须与对面的每个数相乘,因为数都是不同的,所以必须每个数与另一个多项式的每一项相乘(注:一个加号连接两个项),那么根据以上的分析,无论如何都要进行N2次乘法,这样即使采用分治法,最后的时间复杂度也为O(n2)。这个问题让我不得其解,因为不管怎么运用何种算法都不可能减少相乘的次数。然后高斯采用了一个出其不意的思想方法来减少了相乘的次数,变4次大相乘为3次大相乘,而每个数又都相乘了。
该方法的理论依据是:
- 在计算上,乘法比加法更耗时,所以可用加法来代替乘法;
- 该方法来源于反思考宏观的推理。
因此,多项式相乘高效方法来源于高斯的推理。那么首先从多项式的4次分治相乘的编程开始。如何采用分治法进行分割相乘呢?基本的步骤如下:
例如有多项式A=[2,3,5,4]和B=[3,1,3,5] ,注:多项式只存系数,系数的位序代表了该项的幂次。位序==幂次是编程实现的关键。如何关键呢?
Step1. 将A,B分别从中间分割成A0和A1,B0和B1;
Step2. A*B=A0*B0+A0*B1+A1*B0+A1*B1,对这四项进行递归分割相乘,然后叠加;
首先,根据分治法,编写一个主体的递归程序如下:
vector<double> DivideMerge::polynomialsMultiply(vector<double>&numA, int lowA, int highA, vector<double>&numB, int lowB, int highB)
{
vector<double>numXY,numXYZ;
vector<double>numX, numY, numZ;
if (lowA < highA && lowB<highB)
{
int midA = (highA + lowA) / 2;
int midB = (highB + lowB) / 2;