网易实习生笔试题,神奇手环,最开始的方法只过了60%,后来想到可以用矩阵的方法来计算。
一、矩阵相乘
下面的矩阵统一用二维数组来表示,先实现两个矩阵相乘的方法。
1 | public class Matrix { |
输出
1 | [9, 12, 15] |
时间复杂度是O(n^3)
二、矩阵快速幂
矩阵快速幂可以高效地计算矩阵,将O(n)的时间复杂度降到O(logn)。
它的原理与数的快速幂是一样的,先来回忆一下数的快速幂
1、数的快速幂
- Pow(x, n),leetcode原题
1 | public class Solution { |
它的原理就是x^n=x^(n1+n2+n3+…..)=x^n1*xn2*x^n3…,
其中n=n1+n2+n3… 将n用二进制表示,则n1, n2, n3就可以表示为2^0, 2^1, 2^2….
举个例子,x^5=x^4*x^1
这样时间复杂度就从O(n)降到O(logn)。
2、矩阵快速幂
矩阵快速幂的原理与上面是一样的,在编程之美2.9中也介绍到了。
1 | public class Matrix { |
这里又两点需要注意
- 在注释中说到的clone方法无法实现二维数组的深拷贝,由于本例的特殊情况才这样写,正常情况下的二维数组拷贝应该遍历
- 当把上面的参数从4改成8后,输出结果就已经出现负数了,说明已经溢出。而且实际上,即使n等于4的时候,temp中就已经出现负数了。所以可见矩阵乘法的增长速度非常大。在实际情况中,应该使用字符串表示才是最可靠的。
三、矩阵快速幂的应用
1、斐波那契数列
最早接触到矩阵快速幂的时候应该就是编程之美2.9,斐波那契数列的问题。
不会编辑公式,具体问题和与原理就不描述了,直接上代码
1 | public class MatrixApp { |
果然,当输入的n太大后,计算的就不准了,因为超过了int范围。
2、魔幻手环
终于到了这个网易的笔试题,魔幻手环
小易拥有一个拥有魔力的手环上面有n个数字(构成一个环),当这个魔力手环每次使用魔力的时候就会发生一种奇特的变化:每个数字会变成自己跟后面一个数字的和(最后一个数字的后面一个数字是第一个),一旦某个位置的数字大于等于100就马上对100取模(比如某个位置变为103,就会自动变为3).现在给出这个魔力手环的构成,请你计算出使用k次魔力之后魔力手环的状态。
输入描述:
输入数据包括两行:
第一行为两个整数n(2 ≤ n ≤ 50)和k(1 ≤ k ≤ 2000000000),以空格分隔
第二行为魔力手环初始的n个数,以空格分隔。范围都在0至99.
输出描述:
输出魔力手环使用k次之后的状态,以空格分隔,行末无空格。
输入例子:
3 2
1 2 3
输出例子:
8 9 7
1 | public class Main { |
题中特意加了超过100后取模,看来就是为了防止溢出。