在O(n)时间内计算2 ^ n

时间:2015-04-22 05:53:24

标签: algorithm big-o memoization

不使用位移,有没有办法在O(n)时间内计算2 ^ n?

我正在考虑使用memoization的解决方案,因为我将始终从较低的n开始计算。 即

d = dict()
def pwr2(n):
    if n == 0:
       return 1
    if n == 1:
       return 2
    if n in d:
       return d[n]
    d[n] = 2 * pwr2(n-1)
    return d[n]

但我不太清楚复杂性会是什么。

编辑:我应该补充一点,我使用这个算法的一部分,以比O(n ^ 2)时间更快的速度将二进制转换为十进制。作为我的分而治之算法的一部分,我必须乘以增加2的幂,因此我尝试记忆。

EDIT2:只需在此处发布我的完整算法,以帮助解决混淆问题 pwr2dict = dict()

def karatsuba(x, y):
    // use karatsuba's algorithm to multiply x*y


def pwr2(n):
    if n == 0:
        return 1
    if n == 1:
        return 2
    if n in pwr2dict:
        return pwr2dict[n]
    pwr2dict[n] = karatsuba(pwr2(n-1),2)
    return pwr2dict[n]


def binToDec(b):
    if len(b) == 1:
        return int(b)
    n = int(math.floor(len(b)/2))
    top = binToDec(b[:n])  # The top n bits
    bottom = binToDec(b[n:])  # The bottom n bits
    return bottom + karatsuba(top, pwr2(len(b)-n))

print binToDec("10110") // Prints 22

3 个答案:

答案 0 :(得分:2)

我认为你是在思考你的问题。 2^n只是意味着将自身加倍n次。因此,从1到n的简单循环将起到作用: - )

r = 2
for 1 to n do
  r = r * 2
end

这是在O(n)中运行的解决方案,计算2^n的真正问题是,在现代计算机上,您可以在相当小的n内点击架构字长,如32,64或128.然后你必须使用一个任意长度的整数,这可能不会给你很多O(n)时间,但这是一个不同的问题:-)理论上,它可以完成,琐事,在O(n)

修改

好的,所以如果我理解你的话你有一个很长的二进制字符串,并且你想把它转换成十进制。

我按如下方式实施:

将长度为n的二进制字符串放入数组s(可以是位图以节省空间,可以是支持这些字符串的编程语言中的字符串)。反转字符串,使LSB处于索引0(如果不是这种情况)。

e := 1
r := 0
for i := 0 to (n - 1) 
  if s[i] = 1
    r := r + e
  end
  e := e * 2
end

反转字符串可以在O(n)中完成,伪代码只有一个从0n - 1的循环,因此O(n)也是如此。位串反转可以避免在循环中进行简单的算术运算。并非r必须是任意长度的整数形式。

答案 1 :(得分:0)

你实际上可以在O(1)时间内完成。乘以2本身意味着左移n-1位。或左移1位n。

您的问题可以通过以下方式解决。 long k = 2 << n-1. 要么 long k = 1 << n.

不是很简单吗?

修改 我意识到要做到没有位移。你还不需要O(n)时间。可以在O(logn)

中完成
private int power(int x, int n) {

    if (n == 1)
        return x;
    if (n % 2 == 0) {
        int power = power(x, n / 2);
        return power * power;
    } 

    else{
        int power = power(x, (n - 1) / 2);
        return x * power * power;
    }
}

详细了解递归Recursion

答案 2 :(得分:0)

我们可以在Time = T(f(n)) + T(g(n))中实现它,其中f(n)是构建二进制数n二进制数字所需的时间,而g(n)是转换所需的时间这个数字为十进制。

Test Code Online

public BigInteger pow_2 (int n)
{
    String binary = "1";
    for (int i=0; i<n; i++) binary += "0"; // f(n)
    return new BigInteger(binary, 2); // g(n)
}

由于编译器优化,f(n)将获得T(f(n)) Θ(1)

至于代表g(n)构造函数的BigInteger(value,radix)g(n)基于二进制数字的位数,其中二进制中的2^n是一个{{1}的数字数字。