4.2 矩阵乘法,代码如下:
//求两个方阵的乘积 public static int[][] squareMatrixMultiply(int[][] a, int[][] b){ int n = a.length; int[][] c = new int[n][n]; for (int i = 0; i < n; i++){ for (int j = 0; j < n; j++){ c[i][j] = 0; for (int k = 0; k < n; k++){ c[i][j] = c[i][j] + a[i][k] * b[k][j]; } } } return c; }
上述直接计算矩阵乘积的算法时间复杂度有θ(n.^3)。如果采用分治策略,递归算法进行矩阵乘积计算,时间复消耗T(n) = 8T(n/1) + θ(n.^2);
下面介绍一个速度更快的算法,Strassen算法:其实该算法步骤很简单,很好实现,但是实现起来较为繁琐(此处是指用java语言实现),这里就只记下其原理,实现步骤:
(1)将矩阵(方阵,且n是2的幂)A,B,C均分解为四个子矩阵;
(2)创建10个n/2 * n/2的方阵S1,。。。S10,而Sn如下:
S1 = B12-B22;S2=A11+A12;.......S10=B11+B12
(3)用步骤1和步骤2中的矩阵,递归的计算7个矩阵乘积P1,...P7:
P1=A11*S1;P2=S2*B22 ....P7=S9*S10;
(4)对步骤3创建的Pi矩阵进行加减运算,即可求出C的4个子矩阵:
C11=P5+P4-P2+P6;......C22=P5+P1-P3-P7;
从上述步骤可知,个人觉得该算法没有什么特殊意义,就是发现了其中的冗余计算步骤(但是我没仔细推敲),在单纯的分治算法递归的基础上进行一些改进,使基本的8次矩阵乘法,变成了现在的7次矩阵乘法,说明8次矩阵乘法运算中又一次是多余的,就把这次多余的矩阵乘法,通过矩阵加减运算进行替代,提升了算法速度。Strassen使得时间复杂度变为T(n) = 7T(n/2) + θ(n.^2),即n的2次方。
在n较小时,Strassen算法可能不如直接算法快,但当n很大时,Strassen算法会快于直接算法。
在实际应用中,稠密矩阵的快速乘法程序在矩阵规模超过一个交叉点时使用Strassen算法,一旦子问题规模降低到交叉点之下,就切换到一个简单的方法。交叉点的大小依赖于具体系统。