假设整数表示为Fibonacci数的和,而不是2的幂,因此100101
代表F(6)+F(3)+F(1)=8+2+1=11
(我们假设F(1)=F(2)=1
)。我希望在O(1)摊销时间内以此表示形式递增一个整数。
我有增量算法:直觉是不应该有两个连续的1位。所以我首先将最低有效0位设置为1,然后从最高有效位开始,如果数字有两个连续的1位,比如位i和i-1,则将它们都设置为0并设置i + 1 bit to 1.递归执行此操作,直到没有两个连续的1位。
我使用会计方法进行摊销分析。因此,对于每个增量操作,我将授予k美元,并且每个位翻转将花费1美元。但是,我无法设置和证明k的正确值。根据经验,我认为k=3
可以起作用,但我不知道如何证明这一点。
答案 0 :(得分:0)
以下是如何进行的概述。
首先,证明每个整数n
在Fibonacci数中都有唯一表示,没有两个连续的1位。 (更正,最低位为0.我会将该位称为0.)因此,您将从一个开始,应用您的算法,然后结束一个。
其次,证明如果在操作期间i
位翻转,你提出的表示将是位1,2,3,...,i-1中的所有0#1 。 (更正说明,我忽略了第0位。)
接下来,如果在翻转之前i
位为0,那么让我们把它翻转到自身的成本。如果在翻转之前i
位是1,那么让我们把它翻转为2的成本,因为你必须将它翻转到它之前的那个。 (除了第1位的特殊情况。)
如果i
位为0,那么在你前面的序列...010101
之前,你不会再次翻转。您从...000
开始,下一个数字是Fib(i)
,这就是这些位翻转之间的时间长度。从这里你可以设置从i
到0
翻转1
位的成本的上限。 (上限是它总是0。)
如果i
位为1,那么在你前面的序列...101010
之前,你不会再次翻转。您从...000
开始,下一个数字是Fib(i-1)
,这就是这些位翻转之间的时间长度。从这里你可以设置从i
到1
翻转0
位的成本的上限。 (上限是它始终为1.)在Fib(i-1)
小于Fib(i)
的事实与我们将2位翻转到此操作的事实之间,此约束将大于前。
总结这两个界限,你会得出一个分摊上限来计算翻转i
位的成本。此上限将以指数方式衰减。
将所有可能位的上限求和,并且每个操作的位翻转的摊销成本都有一个上限。这将是一个有限的数字。 : - )
答案 1 :(得分:0)
使用电位方法,让表示的电位为1位数。然后递增最低位将电位增加1,因此它仍然是摊销的恒定时间,并且每个进位都是自由摊销的,因为它通过将两位一位变为一位来释放一个势能单位。
答案 2 :(得分:0)
以下是一些命题和观察结果,得出的结论是 k = 3 :
该算法的应用包括单个增量(从 0 到 1 )和零个或多个三重翻转( 011 到 100 )。
运行算法后,可以保证位模式中不再有 11 模式。
增量应用于最右边的位或左边的位,因为算法启动时它们不是 1 。
增量后,最右边的位置或左边的一个位置可能会出现 11 模式。它可能都是( 111 ),但算法会选择左边的算法。
翻转始终执行此子模式转换: 011 - > 100 ,因此每个三元组翻转时1位的数量减少。此外,在tripliet翻转之后保留的1位仅在其右侧具有0位,除了最右位可能是 1 (在增量阶段结果的情况下)在 ... 111 )。
在三元组翻转之后,新的 11 模式可能出现的唯一位置是前一次出现的左侧的两个位位置。所以可能会有一连串的三重翻转向左移动。这个过程是有限的,因为每个三元组翻转时1位的数量会减少。
算法是正确的,因为增量发生在表示值1的位(两个最右边的两个斐波那契数字都是1),因此表示的值增加为1.三重翻转不会由于Fibonacci属性而改变了代表值。
除了最右边的2位之外,所有其他位只能通过在某一点上作为三重态翻转的最左位而成为1位。
为 F i +1 生成的表示,其中 F i 是 i th Fibonacci数大于2,总是恰好有两个1位,包括最右边的位。这是因为对应于值 F i 的位在所有其他位 0 的时刻设置,除了最右边的位。如果最右边的位不是 1 ,则在下一次应用算法时它将变为 1 。因此可以保证将生成 10 ... 01 模式,其值为 F i +1 。
从 0 到 F i +1 执行的增量数量显然是 F 我 1 即可。从 0 到 F i +1 的三元组翻转次数为 F i -1 即可。这是因为增量会使模式中的1位数增加1,而三重翻转会将此数字减少为1.当 F i +1 时有两个1-比 0 的表示更多的位数,三重翻转的数量比增量数少2。
为了增加 i ,达到 F i +1 的增量数和三元组翻转之间的比率收敛为1,因为2的差异变得可以忽略不计。这意味着问题中的 k 收敛到3(三次翻转包含3次翻转)。
请参阅重复应用算法的this JS Fiddle,显示位显示,增量总数和三元组翻转及其比率。看看比率(非常)如何慢慢收敛到1。
上述小提琴算法的实现如下:
// Apply the algorithm once
var mask;
this.bits |= 1 << (this.bits & 1);
this.increments++;
mask = (this.bits & 6) === 6 ? 4
: (this.bits & 3) === 3 ? 2 : 0;
while (this.bits & mask) {
this.bits ^= mask * 3.5; // 3 flips
mask <<= 2;
this.flips++;
}