我是码春儿,将不定期分享面试中遇到的及力扣周赛中的题目,后续会有更多职业中的技术与心得体会分享,欢迎大家关注,让我们一起面向代码,春暖花开!
今天分享一道字节秋招面试中遇到的真题。
题目描述
给定N个矩阵的维度,返回计算其连乘积所需的最小操作数。(矩阵维度一定是可乘的)
示例:
输入:matrix_size: [[10, 10], [10, 10], [10, 1]]
输出:380
解析
两个矩阵相乘所需操作数
计算C=A*B,若A的维度为m×n,B的维度为n×k,则C的维度为,需要计算C中的m×k个数,每个数需要计算两个n维向量的内积,共涉及n次乘法及n-1次加法,因此总操作数为mk(2n-1)。
如何优化矩阵连乘积
一般而言矩阵相乘不具有交换律,但结合律一直满足,因此考虑从结合律入手进行优化,例如计算ABC,其中A、B的维度为10×10,C的维度为10×1,若计算(AB)C则需要1900+190=2090操作数,而计算A(BC)则只需要190+190=380操作数,我们的目标实际上是找出计算的顺序。
暴力求解方法
计算N个矩阵的连乘积需要计算N-1次矩阵乘法,因此暴力求解需要对N-1次计算的所有顺序进行遍历,并找出其中操作数最小的排列顺序,复杂度为N个数的全排列O(N!)
动态规划法
动态规划法是面试中常考的类型,难点在于如何将问题抽象出来,本题可以将矩阵序列拆分为前后两段,并拆解为两个子问题求解,从而“大事化小小事化了”。
记f(i, j)为计算矩阵序列中第i个到第j个所需的最小操作数,显然f(i, i) = 0。
用ri与ci表示第i个矩阵的行数与列数。
记m×n维矩阵与n×k维矩阵相乘的操作数为g(m, n, k) = mk(2n-1)。
例如我们要计算f(1,4) = A1A2A3*A4,共有三种拆解方式:
- 若先计算A2A3A4,则为f(1, 1) + f(2, 4) + g(r1, c1, c4)
- 若先计算A1A2和A3A4,则为f(1, 2) + f(3, 4) + g(r1, c2, c4)
- 若先计算A1A2A3,则为f(1, 3) + f(4, 4) + g(r1, c1, c4)
f(1, 4)的值应取以上三种拆解中最小的值,由此可得出递推公式:
f(i, j) = min{ f(i, k) + f(k + 1, j) + g(r