我已经完成了根据这个简单表达式编写算法的任务:
f (0) = 0, f (1) = 1, f (2n) = f (n), f (2n + 1) = f (n) + f (n + 1).
限制是:时间复杂度O(logn),空间复杂度O(1)。 我写了这个基本的递归函数:
int func (int n) {
if (n == 0) {
return 0;
}
if (n == 1) {
return 1;
}
if (n % 2 == 0) {
return func(n / 2);
} else {
return func(n / 2) + func((n / 2) + 1);
}
}
使用迭代算法可能更聪明,因为我需要O(1)空间复杂度(我认为我的代码不是O(1)空间,因为递归调用)。
答案 0 :(得分:1)
这个序列是斯特恩的双原子序列,你给出的函数称为fusc(n)
。
在O(log n)时间和O(1)空间复杂度中计算它的一种方法是在Calkin-Wilf树中找到第n个值。该值的分子将为fusc(n)
。您可以在维基百科页面上阅读一些背景知识:https://en.wikipedia.org/wiki/Calkin%E2%80%93Wilf_tree
这是一些使用快速版本检查天真fusc
实现的代码。它是在Python中,但转换为C ++会很简单。
def fusc(n):
if n < 2:
return n
if n%2 == 0:
return fusc(n//2)
return fusc(n//2) + fusc(n//2+1)
def fast_fusc(n):
if n == 0: return 0
top = 1
while top <= n:
top <<= 1
top >>= 1
a, b = 1, 1
while top > 1:
top >>= 1
if n & top:
a, b = a + b, b
else:
a, b = a, a + b
return a
for i in xrange(100):
assert fusc(i) == fast_fusc(i)
您可以看到在fast_fusc
中,top
遍历n
的位,因此代码执行O(log n)算术运算。使用的变量只有4个(n
,a
,b
,top
),因此它使用O(1)空格。