提高递归的性能

时间:2017-05-22 20:35:08

标签: java algorithm performance recursion biginteger

我想计算一个序列的大数,这由下面的递归描述:

x(0,w)=1
x(1,w)=w
x(n+1,w)= 2*w*x(n,w)-x(n-1)

我的项目已经用Java实现了,就是我需要一个解决这个问题的Java解决方案。

目的是计算x(k,w),其中w之前已经计算过,k,w是BigIntegers。由于k和w是如此之大的数字,计算需要很多时间。

我已经使用BigIntegers的ArrayList实现了一个解决方案,该解决方案仅适用于小数字。然后,因为我只需要x(k,w)而不是序列的所有数字,我可以提出以下解决方案,这仍然有很多要慢:

BigInteger TWO = new BigInteger("2");

BigInteger x_2 = BigInteger.ONE;
BigInteger x_1 = w;

BigInteger x_0 = BigInteger.ZERO;

for(BigInteger i = BigInteger.ONE; i.compareTo(k) < 0; i = i.add(BigInteger.ONE)) {
        x_0 = w.multiply(TWO).multiply(x_1).subtract(x_2);

        x_2 = x_1;
        x_1 = x_0;

    }

return x_0;

您知道如何提高该算法的速度吗?

一个想法是计算序列的显式函数,该函数应为

x(n,w)=1/2*((w+sqrt(w^2-1)^n+(w-sqrt(w^2-1)^n) 

但Java没有提供实现的方法来计算BigInteger / BigDecimal对象的功率或平方根。人们可以在实际上避免计算平方根,因为它们稍后会被取消。但是,必须计算二项式系数。因此,我不确定应该采用哪种方法。

你能告诉我,你认为哪种(最确切地)计算x(k,w)是最快最有效的方法吗?

1 个答案:

答案 0 :(得分:3)

n - th项是前两项的线性组合,系数对于所有n都相同,因此您可以找到矩阵的n次幂[[2 * w, -1], [1, 0]]并将其乘以向量[x_1, x_0]。如果使用二进制矩阵求幂,则需要O(log n)次乘法和加法。此解决方案仅使用整数,因此它绝对精确。