描述

  • 给定两个 nn的矩阵 A和 B,求 AB 。

  • 数据范围:


方法一

思路

  • 模拟计算
  • 矩阵乘法的规则为:假设矩阵A与矩阵B相乘(默认满足乘法条件),矩阵C为结果,则其满足如下公式:
    图片说明
  • 故要求矩阵C,只需模拟上述公式的过程,求出每一个位置的值即可。

具体步骤

  • 1.首先calculate函数是用于计算指定位置的值的;
  • 2.循环遍历矩阵C的每一个位置,使用calculate计算该位置的值;
  • 3.遍历完成,C矩阵也就出来了。
  • 代码如下:
    import java.util.*;
    public class Solution {
    /**
    * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
    * 
    * @param a int整型二维数组 第一个矩阵
    * @param b int整型二维数组 第二个矩阵
    * @return int整型二维数组
    */
    public int[][] solve (int[][] a, int[][] b) {
       //矩阵相乘后的行数等于第一个矩阵的行数,列数等于第二个矩阵的列数
        int[][] res =new int[a.length][b[0].length];
       for(int i = 0;i < a.length;++i){
           for(int j = 0;j < a.length;++j){
               int sum = 0;
               for(int k = 0;k < a.length;++k){
                  sum += a[i][k] * b[k][j];
               }
               res[i][j] = sum;
           }
       }
       return res;
    }
    }
  • 时间复杂度:,calculate一重循环,主函数中双重循环,所以是
  • 空间复杂度:,res矩阵所需空间为

方法二

思路

  • 缓存优化
  • 一个编写良好的计算机程序常常具有良好的局部性,也就是它们倾向于应用邻近于其它最近引用过的数据项的数据项,或者最近引用过的数据项本身,这种倾向性被称为局部性原理。
  • 局部性分为空间局部性和时间局部性,而有良好局部性的程序比局部性差的程序运行得更快,在一个具有良好的空间局部性的程序中,如果一个内存位置被引用了,那么程序很可能在不久的未来引用附近的一个内存位置。
  • 而像本题中用于存储矩阵的二维数组,其在空间中实际上是顺序存储的,而方法一种对于矩阵数据的读取实际上是跳着读取的,其并不具备良好的空间局部性。
    图片说明
  • 故可以通过顺序读取矩阵中的数据来进行矩阵乘法,从而提高程序的空间局部性,来提高算法的速度。
  • 对局部性这些问题感兴趣的可以看看CSAPP这本书。

    具体步骤

  • 代码如下:
    import java.util.*;
    public class Solution {
      /**
       * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
       * 
       * @param a int整型二维数组 第一个矩阵
       * @param b int整型二维数组 第二个矩阵
       * @return int整型二维数组
       */
      public int[][] solve (int[][] a, int[][] b) {
          //矩阵相乘后的行数等于第一个矩阵的行数,列数等于第二个矩阵的列数
           int[][] res =new int[a.length][b[0].length];
          for(int i = 0;i < a.length;++i){
              for(int j = 0;j < a.length;++j){
                  // 优先访问
                  int temp = a[i][j];
                  for(int k = 0;k < a.length;++k){
                     // 行*列相加
                     res[i][k] += temp * b[j][k];
                  }
              }
          }
          return res;
      }
    }
  • 时间复杂度:,三重循环;
  • 空间复杂度:,结果矩阵需要的空间。
  • 方法一和方法二的时间复杂度为,是比较大的,那么有没有更优的算法来实现矩阵乘法呢?
    当然是有的,1969年,Volker Strassen提出了第一个算法时间复杂度低于的矩阵乘法算法,算法复杂度约为 。但是Strassen算法只有在对于维数比较大的矩阵,性能上才有很大的优势,可以减少很多乘法计算。Strassen算法证明了矩阵乘法存在时间复杂度低于 的算法的存在,后续学者不断研究发现新的更快的算法,截止目前时间复杂度最低的矩阵乘法算法是Coppersmith-Winograd方法的一种扩展方法.
  • Strassen算法笔者就不具体介绍了,感兴趣的可以自己百度,下面就来实现这个算法吧。
  • 当然也可以通过使用多线程来进行矩阵乘法的运算,从而降低算法的运行时间。