根据
Zeckendorf’s theorem,每个正整数可以以独特的方式写为非连续不同Fibonacci数的总和.使用贪婪算法可以很容易地找到这样的分解,该算法主要包括减去适合和迭代的最大Fibonacci数,例如:
20 = 13 7 = 13 5 2
然而,该定理还暗示任何整数(也<= 0)具有唯一分解作为不同的,非连续的negaFibonacci数的总和,即序列 0,1,-1,2,-3,5,-8,…… 或F _( – n)=( – 1)^(n 1)F_n.一些例子: -4 = – 3 – 1 4 = 5 1 11 = 13 – 3 1 是否有一种已知的简单算法以这种方式分解给定的整数?
最佳答案 有一个很好的贪婪算法,你可以用来表示negafibonacci中的数字.
这个算法背后的想法是将整数分成由偶数Fibonacci数(在正例中)和奇数Fibonacci数(在负例中)分隔的范围.具体来说,我们将正数分成范围
> F0 1到F2,包括,
> F2 1至F4,包括在内
> F4 1至F6,包括,
> F6 1至F8,包括在内,
> F8 1至F10,含,
> ……
> F2k 1至F2k 2,含,
> ……
我们将类似地将n个数字分成由负Fibonacci数划分的这些范围:
> -F1到-F3 1,包括端点,
> -F3到-F5 1,包括端点,
> -F5到-F7 1,包括端点,
> -F7到-F9 1,包括端点,
> ……
> -F2k-1到-F2k 1 1,包括端点,
> ……
贪心算法然后如下进行:
>如果数字为正,找到包含n的范围[F2k 1,F2k 2],将F2k 1添加到表示中,并从n中减去F2k 1.
>如果数字为负数,找到包含n的范围[-F2k-1,-F2k 1 1],将-F2k添加到表示中,并将F2k添加到总数中.
>如果数字为零,那么你已经完成了.
我们举个例子.假设我想将27转换为negafibonacci.我发现211≤27≤55.这将(奇数指数)Fibonacci数字34夹在中间,所以我将总数加34,然后尝试将27 – 34 = -7转换为negafibonacci.
接下来,我们注意到51≤7≤13,因此7被夹在包含(偶数索引)Fibonacci数8的范围内.因此,我们在总数中加入-8并尝试将1转换为negafibonacci.
现在,我们注意到01≤1≤1,因此1夹在包含(奇数索引)Fibonacci数1的范围内.因此,我们在总数中加1,并尝试将0转换为negafibonacci.
这总共留下了0,所以我们完成了!嘿! 34 – 8 1 = 27.
让我们首先论证正确性.首先,注意如果我们加上一个正的Fibonacci数,它必须是一个奇数的Fibonacci数(因为我们选择了F2k 1的形式),如果我们加上一个负的Fibonacci数,它必须是负数-numbered Fibonacci数字(因为我们选择了-F2k形式的东西).因此,添加的每个数字都将具有正确的符号.
接下来,我们将证明终止.先看看积极的情况.如果我们发现我们的数字在[F2k 1,F2k 2]范围内,那么我们减去F2k 1.数字的上限是F2k 2 – F2k 1 = F2k,所以包含余数的最大区间将是落在[F2k-2 1,F2k]范围内,我们可以拉出的最高斐波纳契数是F2k-1.因此,我们不能重复我们之前删除的斐波纳契数,并且正数之间会有差距拉出来.
数字的下限是F2k 1 – F2k 1 = -F2k-1 1.这意味着如果数字为负数,则包含它的“最高”负区间将是[F2k-1 1,F2k-3],所以我们可以得出的最高负Fibonacci数是F2k-2.因此,我们将提出一个低阶Fibonacci数.
我们可以做类似的数学运算来证明拉出负的斐波纳契数会使我们的窗口向下移动一步.
为了有效地实现这一点,我们可以跟踪三个连续的斐波纳契数(Fk-1,Fk,Fk 1)并继续向上(或向下)移动,直到找到包含数字n的范围.然后我们可以拉出我们的(可能是负的)斐波纳契数,然后将窗口移回0直到我们完成.总的来说,这将在时间O(log n)中运行.