70

有几十种方法可以计算任意 n 的 F(n),其中许多具有很好的运行时间和内存使用率。

但是,假设我想问相反的问题:

给定 n > 2 的 F(n),n 是多少?

(由于 F(1) = F(2) = 1 存在 n > 2 限制,并且没有明确的逆)。

解决这个问题的最有效方法是什么?通过枚举斐波那契数并在达到目标数时停止,在线性时间内很容易做到这一点,但是有没有比这更快的方法呢?

编辑:目前,此处发布的最佳解决方案使用 O(log n) 内存在 O(log n) 时间内运行,假设数学运算在 O(1) 中运行并且机器字可以在 O(1) 空间中保存任何数字. 我很好奇是否可以降低内存要求,因为您可以使用 O(1) 空间计算斐波那契数。

4

10 回答 10

52

由于 OP 询问了不涉及任何浮点计算的矩阵解决方案,因此它就是这样。O(logn)假设数值运算具有复杂性,我们可以通过这种方式实现复杂O(1)性。

让我们采用A具有以下结构的 2x2 矩阵

1 1
1 0

现在考虑 vector (8, 5),存储两个连续的斐波那契数。如果你将它乘以这个矩阵,你会得到(8*1 + 5*1, 8*1 + 5*0) = (13, 8)- 下一个斐波那契数。
如果我们概括,A^n * (1, 0) = (f(n), f(n - 1)).

实际的算法需要两个步骤。

  1. 计算A^2A^4A^8等,直到我们通过所需的数字。
  2. n使用 的计算幂进行二分搜索A

附带说明一下,任何形式的序列f(n) = k1*f(n-1) + k2*f(n-2) + k3*f(n-3) + .. + kt*f(n-t)都可以这样呈现。

于 2011-03-02T03:51:52.773 回答
43

维基百科给出的结果为

n(F) = Floor[ Log(F Sqrt(5) + 1/2)/Log(Phi)]

其中 Phi 是黄金比例。

于 2011-03-02T02:44:59.213 回答
13

如果您可以轻松地用二进制解释 F(n),

公式

你可能会怀疑常量 1.7 和 1.1。这些工作是因为 d*1.44042009041 + C 永远不会非常接近整数。

如果有兴趣,我明天可以发布推导。

这是一个 n = 2 到 91 的表格,它显示了地板之前的公式结果:

 n  formula w/o floor     F(n) F(n) in binary

 2  2.540                    1 1
 3  3.981                    2 10
 4  4.581                    3 11
 5  5.421                    5 101
 6  6.862                    8 1000
 7  7.462                   13 1101
 8  8.302                   21 10101
 9  9.743                   34 100010
10 10.343                   55 110111
11 11.183                   89 1011001
12 12.623                  144 10010000
13 13.223                  233 11101001
14 14.064                  377 101111001
15 15.504                  610 1001100010
16 16.104                  987 1111011011
17 17.545                 1597 11000111101
18 18.385                 2584 101000011000
19 19.825                 4181 1000001010101
20 20.425                 6765 1101001101101
21 21.266                10946 10101011000010
22 22.706                17711 100010100101111
23 23.306                28657 110111111110001
24 24.147                46368 1011010100100000
25 25.587                75025 10010010100010001
26 26.187               121393 11101101000110001
27 27.028               196418 101111111101000010
28 28.468               317811 1001101100101110011
29 29.068               514229 1111101100010110101
30 30.508               832040 11001011001000101000
31 31.349              1346269 101001000101011011101
32 32.789              2178309 1000010011110100000101
33 33.389              3524578 1101011100011111100010
34 34.230              5702887 10101110000010011100111
35 35.670              9227465 100011001100110011001001
36 36.270             14930352 111000111101000110110000
37 37.111             24157817 1011100001001111001111001
38 38.551             39088169 10010101000111000000101001
39 39.151             63245986 11110001010000111010100010
40 40.591            102334155 110000110010111111011001011
41 41.432            165580141 1001110111101000110101101101
42 42.032            267914296 1111111110000000110000111000
43 43.472            433494437 11001110101101001100110100101
44 44.313            701408733 101001110011101010010111011101
45 45.753           1134903170 1000011101001010011111110000010
46 46.353           1836311903 1101101011100111110010101011111
47 47.193           2971215073 10110001000110010010010011100001
48 48.634           4807526976 100011110100011010000101001000000
49 49.234           7778742049 111001111101001100010111100100001
50 50.074          12586269025 1011101110001100110011100101100001
51 51.515          20365011074 10010111101110110010110100010000010
52 52.115          32951280099 11110101100000011001010000111100011
53 53.555          53316291173 110001101001111001100000101001100101
54 54.396          86267571272 1010000010101111100101010110001001000
55 55.836         139583862445 10000001111111110110001011011010101101
56 56.436         225851433717 11010010010101110010110110001011110101
57 57.276         365435296162 101010100010101101001000001100110100010
58 58.717         591286729879 1000100110101011011011110111110010010111
59 59.317         956722026041 1101111011000001000100111001011000111001
60 60.157        1548008755920 10110100001101100100000110001001011010000
61 61.598        2504730781961 100100011100101101100101101010100100001001
62 62.198        4052739537881 111010111110011010000110011011101111011001
63 63.038        6557470319842 1011111011011000111101100000110010011100010
64 64.478       10610209857723 10011010011001100001110010100010000010111011
65 65.078       17167680177565 11111001110100101001011110101000010110011101
66 66.519       27777890035288 110010100001110001011010001001010011001011000
67 67.359       44945570212853 1010001110000010110100101111110010101111110101
68 68.800       72723460248141 10000100010010001000000000000111101001001001101
69 69.400      117669030460994 11010110000010011110100110000101111111001000010
70 70.240      190392490709135 101011010010100100110100110001101101000010001111
71 71.681      308061521170129 1000110000010111000101001100010011100111011010001
72 72.281      498454011879264 1110001010101011101011110010100001001111101100000
73 73.121      806515533049393 10110111011000010110000111110110100110111000110001
74 74.561     1304969544928657 100101000101101110011100110001010110000110110010001
75 75.161     2111485077978050 111100000000110001001101110000001010111101111000010
76 76.602     3416454622906707 1100001000110011111101010100001100001000100101010011
77 77.442     5527939700884757 10011101000111010000111000010001101100000010100010101
78 78.042     8944394323791464 11111110001101110000100010110011001101000111001101000
79 79.483    14472334024676221 110011011010101000001011011000100111001001001101111101
80 80.323    23416728348467685 1010011001100010110001111101111000000110010000111100101
81 81.764    37889062373143906 10000110100110111110011011000111100111111011010101100010
82 82.364    61305790721611591 11011001110011010100101010110110101000101101011101000111
83 83.204    99194853094755497 101100000011010010011000101111110010000101000110010101001
84 84.644   160500643816367088 1000111010001101100111110000110100111001010110001111110000
85 85.244   259695496911122585 1110011010100111111010110110110011001001111111000010011001
86 86.085   420196140727489673 10111010100110101100010100111101000000011010101010010001001
87 87.525   679891637638612258 100101101111011101011101011110011011001101010100010100100010
88 88.125  1100087778366101931 111101000100010011000000000110000011010000101001100110101011
89 89.566  1779979416004714189 1100010110011110000011101100100011110011101111101111011001101
90 90.406  2880067194370816120 10011111111000000011011101101010100001101110100111100001111000
91 91.846  4660046610375530309 100000010101011110011111011001111000000001100100101011101000101

'

于 2011-03-10T02:27:32.223 回答
11

通过计算无界单词来测量内存使用情况有点愚蠢,但只要是模型,就有O(log n) 时间,O(1) 单词解决方案,类似于 Nikita Rybak 的,本质上是n通过其Zeckendorf 表示来计算的,即基于斐波那契数(YO DAWG)。

定义矩阵

      1  1
A  =       ,
      1  0

满足

        F(m + 1)    F(m)
A^m  =                      .
          F(m)    F(m - 1)

A^(2^k)我们将使用序列而不是序列A^F(k)。后一个序列具有我们可以通过矩阵乘法向前移动的特性

A^F(k + 1) = A^F(k - 1) * A^F(k)

并用矩阵求逆和乘法向后

A^F(k - 1) = A^F(k + 1) (A^F(k))^-1,

所以我们可以建立一个只有 六十二个单词的双向迭代器,假设我们将所有内容都存储为有理数(以避免假设存在单位成本鸿沟)。剩下的只是调整这个 O(1) 空间算法来寻找 Zeckendorf 表示。

def zeck(n):
    a, b = (0, 1)
    while b < n:
        a, b = (b, a + b)
    yield a
    n1 = a
    while n1 < n:
        a, b = (b - a, a)
        if n1 + a <= n:
            yield a
            n1 += a
            a, b = (b - a, a)

>>> list(zeck(0))
[0]
>>> list(zeck(2))
[1, 1]
>>> list(zeck(12))
[8, 3, 1]
>>> list(zeck(750))
[610, 89, 34, 13, 3, 1]
于 2011-03-06T03:00:11.043 回答
3

已经证明 fib n 的公式是fib(n) = ( (phi)^n - (-phi)^(-n) ) / sqrt(5)where phi = (1+sqrt(5)) / 2,即黄金分割数。(请参阅此链接)。

您可以尝试找到上述 fib 函数的数学逆运算,或者在 32/64 操作中进行二进制搜索(取决于可搜索的最大值有多大)以找到与数字匹配的 n(通过计算 fib 尝试每个 n (n) 并根据 fib(n) 与给定斐波那契数的比较将样本空间分成两部分)。

编辑:@rcollyer 的解决方案更快,因为我的解决方案在 O(lg n) 中,而他发现的解决方案在 O(1) = 恒定时间中。

于 2011-03-02T02:44:29.813 回答
2

所以我在考虑这个问题,我认为可以在 O(lg n) 时间内使用 O(lg n) 内存使用来完成此操作。这是基于以下事实

F(n) = (1 / √5) (Φ n - φ n )

其中 Φ = (1 + √5)/2 且 φ = 1 - Φ。

第一个观察结果是对于任何 n > 1,φ n < 1。这意味着对于任何 n > 2,我们有

F(n) = ⌊ Φ n / √5 ⌋

现在,取 n 并将其以二进制形式写为 b k-1 b k-2 ...b 1 b 0。这意味着

n = 2 k-1 b k-1 + 2 k-2 b k-2 + ... + 2 1 b 1 + 2 0 b 0

这意味着

F(n) = ⌊ Φ 2 k-1 b k-1 + 2 k-2 b k-2 + ... + 2 1 b 1 + 2 0 b 0 / √5 ⌋

或者,更易读的是,

F(n) = ⌊ Φ 2 k-1 b k-1 Φ 2 k-2 b k-2 ... Φ 2 1 b 1 Φ 2 0 b 0 / √5 ⌋

这提出了以下算法。首先,开始计算所有 k 的 Φ 2 k,直到你计算出一个数字 Φ z使得 ⌊ Φ z / √5 ⌋ 大于你的数字 F(n)。现在,从那里开始,向后迭代您以这种方式生成的所有 Φ 幂。如果当前数大于指示的 Φ 的幂,则将其除以 Φ 的幂,并记录该数除以该值。这个过程本质上是通过一次减去 2 的最大幂来一次恢复 n 的一位。因此,一旦你完成了,你就会找到 n。

该算法的运行时间为 O(lg n),因为您可以通过重复平方生成 Φ 2 i ,而我们只生成 O(lg n) 项。内存使用量为 O(lg n),因为我们存储了所有这些值。

于 2011-03-02T02:52:38.153 回答
2

您可以在 O(1) 时间和 O(1) 空间中找到任何 Fib(n) 的 n。

您可以使用定点 CORDIC 算法来计算 ln(),仅使用移位和加法整数数据类型。

如果 x = Fib(n),则 n 可以由下式确定

     n = int(2.0801 * ln(x) + 2.1408)

CORDIC 运行时间由所需的精度级别决定。这两个浮点值将被编码为定点值。

这个提议的唯一问题是它返回一个不在斐波那契数列中的数字的值,但最初的问题特别指出函数的输入是 Fib(n),这意味着只有有效的斐波那契数是用过的。

于 2011-03-10T22:47:04.817 回答
1

编辑:没关系。提问者在评论中表示,幂绝对不是常数时间。


取幂是您在恒定时间内允许的数学运算之一吗?如果是这样,我们可以通过闭式公式在恒定时间内计算 F(n) 。然后,给定一些 F,我们可以执行以下操作:

  1. 计算 F(1), F(2), F(4), F(16), F(256), ... 直到 F(2^k) <= F < F(2^{k+1})
  2. 在 2^k 和 2^{k+1} 之间对 i 进行二分搜索,直到 F(i) <= F < F(i+1)

如果 F = F(n),那么第一部分需要 k = O(log(n)) 步。第二部分是在 O(2^k) 大小范围内的二分搜索,因此它也需要 k = O(log(n))。所以,总的来说,我们在 O(1) 空间中有 O(log(n)) 时间,如果(这是一个很大的如果)我们在 O(1) 时间内有幂运算。

于 2011-03-10T05:25:35.243 回答
1

斐波那契数公式的封闭形式是:

Fn = Round(φ^n / Sqrt(5))

其中φ是黄金比例。

如果我们忽略舍入因子,这是可逆的,反函数为:

F(-1)n= log(n*Sqrt(5))/logφ 

因为我们忽略了舍入因子,所以可以计算公式中的错误。然而,如果我们认为一个数 n 是一个斐波那契数,如果区间 [n*φ - 1/n, n*φ + 1/n] 包含一个自然数,那么:

如果区间 [n*φ - 1/n, n*φ + 1/n] 包含一个自然数,并且该数在斐波那契数列中的索引由四舍五入 log(n*Sqrt(5) )/logφ

这应该在(伪)恒定时间内可行,具体取决于用于计算对数和平方根等的算法。

编辑:φ = (1+Sqrt(5))/2

于 2011-09-09T12:12:15.567 回答
1

这可能类似于 user635541 的回答。我不完全理解他的做法。

使用其他答案中讨论的斐波那契数的矩阵表示,我们得到了一种在恒定时间内往返和F_n往返的方法,只使用加、乘、减和除(实际上不是!请参阅更新)。我们还有一个零(单位矩阵),所以它是一个数学群!F_mF_{n+m}F_{n-m}

通常在进行二分搜索时,我们还需要一个除法运算符来取平均值。或者至少除以 2。但是,如果我们想从F_{2n}F_n它需要一个平方根。幸运的是,加号和减号是我们对数时间“几乎”二分搜索所需要的!

Wikipedia 写了这个方法,讽刺地称为Fibonacci_search,但是文章写得不是很清楚,所以我不知道它是否和我的方法完全一样。了解用于斐波那契搜索的斐波那契数与我们正在寻找的数无关是非常重要的。这有点令人困惑。为了演示该方法,这里首先是一个仅使用加号和减号的标准“二分搜索”的实现:

def search0(test):
    # Standard binary search invariants:
    #   i <= lo then test(i)
    #   i >= hi then not test(i)
    # Extra invariants:
    #   hi - lo = b
    #   a, b = F_{k-1}, F_k
    a, b = 0, 1
    lo, hi = 0, 1
    while test(hi):
        a, b = b, a + b
        hi = b
    while b != 1:
        mi = lo + a
        if test(mi):
            lo = mi
            a, b = 2*a - b, b - a
        else:
            hi = mi
            a, b = b - a, a
    return lo

>>> search0(lambda n: n**2 <= 25)
5
>>> search0(lambda n: 2**n <= 256)
8

test是一些布尔函数;ab是连续的斐波那契数f_kf_{k-1}因此上界hi和下界之间的差lo总是f_k. 我们两者都需要ab因此我们可以有效地增加和减少隐式变量k

好的,那么我们如何使用它来解决问题呢?我发现围绕我们的斐波那契表示创建一个包装器很有用,它隐藏了矩阵细节。在实践中(斐波那契搜索器有这样的事情吗?)您会想要手动内联所有内容。这样可以避免矩阵中的冗余,并围绕矩阵求逆进行一些优化。

import numpy as np
class Fib:
    def __init__(self, k, M):
        """ `k` is the 'name' of the fib, e.g. k=6 for F_6=8.
             We need this to report our result in the very end.
            `M` is the matrix representation, that is
             [[F_{k+1}, F_k], [F_k, F_{k-1}]] """
        self.k = k
        self.M = M
    def __add__(self, other):
        return Fib(self.k + other.k, self.M.dot(other.M))
    def __sub__(self, other):
        return self + (-other)
    def __neg__(self):
        return Fib(-self.k, np.round(np.linalg.inv(self.M)).astype(int))
    def __eq__(self, other):
        return self.k == other.k
    def value(self):
        return self.M[0,1]

但是代码确实有效,因此我们可以按如下方式对其进行测试。请注意,当我们的对象是整数而不是斐波那契时,搜索功能几乎没有什么不同。

def search(test):
    Z = Fib(0, np.array([[1,0],[0,1]])) # Our 0 element
    A = Fib(1, np.array([[1,1],[1,0]])) # Our 1 element
    a, b = Z, A
    lo, hi = Z, A
    while test(hi.value()):
        a, b = b, a + b
        hi = b
    while b != A:
        mi = lo + a
        if test(mi.value()):
            lo = mi
            a, b = a+a-b, b-a
        else:
            hi = mi
            a, b = b-a, a
    return lo.k

>>> search(lambda n: n <= 144)
12
>>> search(lambda n: n <= 0)
0

剩下的悬而未决的问题是是否有一种有效的幺半群搜索算法。那是不需要减/加逆的。我的猜测是否定的:没有减号你需要 Nikita Rybak 的额外记忆。

更新

我刚刚意识到我们根本不需要分裂。矩阵的F_n行列式是(-1)^n,所以我们实际上可以在没有除法的情况下做任何事情。在下面我删除了所有的矩阵代码,但我保留了Fib课程,因为否则一切都会变得非常混乱。

class Fib2:
    def __init__(self, k, fp, f):
        """ `fp` and `f` are F_{k-1} and F_{k} """
        self.k, self.fp, self.f = k, fp, f
    def __add__(self, other):
        fnp, fn, fmp, fm = self.fp, self.f, other.fp, other.f
        return Fib2(self.k + other.k, fn*fm+fnp*fmp, (fn+fnp)*fm+fn*fmp)
    def __sub__(self, other):
        return self + (-other)
    def __neg__(self):
        fp, f = self.f + self.fp, -self.f
        return Fib2(-self.k, (-1)**self.k*fp, (-1)**self.k*f)
    def __eq__(self, other):
        return self.k == other.k
    def value(self):
        return self.f

def search2(test):
    Z = Fib2(0, 1, 0)
    A = Fib2(1, 0, 1)
    ...

>>> search2(lambda n: n <= 280571172992510140037611932413038677189525)
200
>>> search2(lambda n: n <= 4224696333392304878706725602341482782579852840250681098010280137314308584370130707224123599639141511088446087538909603607640194711643596029271983312598737326253555802606991585915229492453904998722256795316982874482472992263901833716778060607011615497886719879858311468870876264597369086722884023654422295243347964480139515349562972087652656069529806499841977448720155612802665404554171717881930324025204312082516817125)
2000
>>> search2(lambda n: n <= 2531162323732361242240155003520607291766356485802485278951929841991312781760541315230153423463758831637443488219211037689033673531462742885329724071555187618026931630449193158922771331642302030331971098689235780843478258502779200293635651897483309686042860996364443514558772156043691404155819572984971754278513112487985892718229593329483578531419148805380281624260900362993556916638613939977074685016188258584312329139526393558096840812970422952418558991855772306882442574855589237165219912238201311184749075137322987656049866305366913734924425822681338966507463855180236283582409861199212323835947891143765414913345008456022009455704210891637791911265475167769704477334859109822590053774932978465651023851447920601310106288957894301592502061560528131203072778677491443420921822590709910448617329156135355464620891788459566081572824889514296350670950824208245170667601726417091127999999941149913010424532046881958285409468463211897582215075436515584016297874572183907949257286261608612401379639484713101138120404671732190451327881433201025184027541696124114463488665359385870910331476156665889459832092710304159637019707297988417848767011085425271875588008671422491434005115288334343837778792282383576736341414410248994081564830202363820504190074504566612515965134665683289356188727549463732830075811851574961558669278847363279870595320099844676879457196432535973357128305390290471349480258751812890314779723508104229525161740643984423978659638233074463100366500571977234508464710078102581304823235436518145074482824812996511614161933313389889630935320139507075992100561077534028207257574257706278201308302642634678112591091843082665721697117838726431766741158743554298864560993255547608496686850185804659790217122426535133253371422250684486113457341827911625517128815447325958547912113242367201990672230681308819195941016156001961954700241576553750737681552256845421159386858399433450045903975167084252876848848085910156941603293424067793097271128806817514906531652407763118308162377033463203514657531210413149191213595455280387631030665594589183601575340027172997222489081631144728873621805528648768511368948639522975539046995395707688938978847084621586473529546678958226255042389998718141303055036060772003887773038422366913820397748550793178167220193346017430024134496141145991896227741842515718997898627269918236920453493946658273870473264523119133765447653295022886429174942653014656521909469613184983671431465934965489425515981067546087342348350724207583544436107294087637975025147846254526938442435644928231027868701394819091132912397475713787593612758364812687556725146456646878912169274219209708166678668152184941578590201953144030519381922273252666652671717526318606676754556170379350956342095455612780202199922615392785572481747913435560866995432578680971243966868110016581395696310922519803685837460795358384618017215468122880442252343684547233668502313239328352671318130604247460452134121833305284398726438573787798499612760939462427922917659263046333084007208056631996856315539698234022953452211505675629153637867252695056925345220084020071611220575700841268302638995272842160994219632684575364180160991884885091858259996299627148614456696661412745040519981575543804847463997422326563897043803732970397488471644906183310144691243649149542394691524972023935190633672827306116525712882959108434211652465621144702015336657459532134026915214509960877430595844287585350290234547564574848753110281101545931547225811763441710217452979668178025286460158324658852904105792472468108996135476637212057508192176910900422826969523438985332067597093454021924077101784215936539638808624420121459718286059401823614213214326004270471752802725625810953787713898846144256909835116371235019527013180204030167601567064268573820697948868982630904164685161783088076506964317303709708574052747204405282785965604677674192569851918643651835755242670293612851920696732320545562286110332140065912751551110134916256237884844001366366654055079721985816714803952429301558096968202261698837096090377863017797020488044826628817462866854321356787305635653577619877987998113667928954840972022833505708587561902023411398915823487627297968947621416912816367516125096563705174220460639857683971213093125)
20000

这一切都像一个魅力。我唯一担心的是这种位复杂性在计算中占主导地位,我们还不如只进行顺序搜索。或者实际上,仅查看位数可能就可以告诉您您正在查看的内容。但这并不那么有趣。

于 2014-06-14T23:47:38.060 回答