给定递归表达式,找到空间复杂度为O(1)的算法

时间:2018-04-24 19:39:24

标签: c++ algorithm recursion

我已经完成了根据这个简单表达式编写算法的任务:

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)空间,因为递归调用)。

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个(nabtop),因此它使用O(1)空格。