题意整理:
本题题意非常清晰,就是求出两个矩阵的矩阵乘积
对于两个矩阵,设 为 的矩阵, 为 的矩阵,那么它们的乘积结果为一个 的矩阵 。其中, 的第 行第 列的元素计算方法如下
需要注意的是,只有矩阵的列数和矩阵的行数相同的时候,两个矩阵才能进行乘法
对于本题,给定的两个矩阵维数相同,所以无需判断。
方法一:暴力模拟
核心思想:
直接根据上述公式,进行模拟后计算即可。具体实现为枚举矩阵 的行以及矩阵 的列,第三维的 枚举上述公式的 1 到 p 进行计算即可。
核心代码:
class Solution { public: vector<vector<int> > solve(vector<vector<int> >& a, vector<vector<int> >& b) { int n = a.size(); vector<vector<int>> ans(n, vector<int>(n)); //用于存储结果 for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) for(int k = 0; k < n; k++) { ans[i][j] += a[i][k] * b[k][j]; //行*列相加 } return ans; } };
复杂度分析:
时间复杂度:,使用了三重循环,枚举行列以及对单个元素进行计算。
空间复杂度:,不计算答案数组,使用的空间为常数个遍历
方法二:暴力法的优化
核心思想:
此优化需要一些对操作系统的知识。
二维矩阵实际上是转换为一维形式存储的。如下图
而对于CPU的数据读取,对连续数据的读取的效率的高于跳跃性的读取的。在方法一中,对单个元素 的计算中,需要跳跃性的对矩阵 进行访问,这会使得效率下降。我们可以通过调整枚举的顺序进行优化,使得两个矩阵的读取都为顺序读取。虽然时间复杂度不变,但基于CPU的连续读取特性,实际运行效率会比方法一高。
核心代码:
class Solution { public: vector<vector<int> > solve(vector<vector<int> >& a, vector<vector<int> >& b) { int n = a.size(); int res; vector<vector<int> > ans(n, vector<int>(n)); //用于存储结果 for(int i = 0; i < n; i++) for(int k = 0; k < n; k++){ res = a[i][k]; for(int j = 0; j < n; j++) { ans[i][j] += res * b[k][j]; //行*列相加 } } return ans; } };
复杂度分析:
时间复杂度:,使用了三重循环,枚举行列以及对单个元素进行计算。虽然时间复杂度不变,但对于较大矩阵,本方法比方法一要快很多。
空间复杂度:,不计算答案数组,使用的空间为常数个遍历