闲来无事刷题,看到一道极其古老的斐波那契数列求和,想起了校招时华为面试官给我出的就是这道,当时要求在10分钟内写出递归和非递归的解法,并且大致问了下递归解法的坏处(栈溢出)就结束了,后续也一直把其当作一个简单题来对待,想当然的认为其最好的时间复杂度就是O(n),直到有一天意外接触到了快速幂的概念…
整数快速幂
什么是快速幂,以整数为例,在求an时,按正常思路是让a累乘n次,时间复杂度为O(n);而在快速幂算法下,将an变换为am1(a2)m2(a4)m3(a8)m4……即为把n按2进制进行拆解后分段计算,从而把时间复杂度降低到O(logN)。
我们来举几个直观的例子:
a15 = a*a2*a4*a8
本来累乘15次,使用快速幂后仅需累乘7次,其中a,a2,a4,a8通过翻倍累乘的方式使用了4次,而他们之间相乘又使用了3次。
a8 = ((a2)2)2
本来应该累乘8次,使用快速幂只需翻倍累乘3次即可得出结果。
如果还是不太明确为什么可以做到O(logN)的时间复杂度,我们来看代码:
/*
通过移位的方式来进行二进制拆解,并按2^n翻倍累乘底数
*/
public int quickPow(int num, int n) {
int sum = 1;
while(n != 0) {
if((n & 1) != 0) {
sum *= num;
}
n >>= 1;
num *= num;
}
return sum;
}
Ok,,到这里我们就基本弄明白了整数快速幂的概念,下面再引申到矩阵快速幂。
矩阵快速幂
我们假设创建一个矩阵A,根据线性代数,矩阵乘法是满足结合律的,即:
A8 = (A2)(A2)(A2)(A2) = ((A2)2)2
由此可见,快速幂的概念同样可以应用到矩阵乘法上来,只是在实现