44. log(n)求a的n次方[power(a,n)]

【题目】

实现函数double Power(double base, int exponent),求base的exponent次方,不需要考虑溢出。

【分析】

这是一道看起来很简单的问题,很容易写出如下的代码:

 C++ Code 
1
2
3
4
5
6
7
8
9
 

double Power(double base, int exponent)
{
    
double result = 1.0;
    
for(int i = 1; i <= exponent; ++i)
        result *= base;

    
return result;
}

上述代码存在的问题:

(1) 由于输入的exponent是个int型的数值,因此可能为正数,也可能是负数,上述代码只考虑了exponent为正数的情况。

(2) 底数为0,指数为负数,则输入非法。

改进之后代码如下:

【代码1】

 

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
 

bool g_bValid = true;

bool Equal(double num1, double num2)
{
    
double gap = 0.00000001;
    
if (num1 - num2 > -gap && num1 - num2 < gap)
        
return true;
    
return false;
}

double PowerWithUnsignedExponent(double base, unsigned int exponent)
{
    
// T(n) = O(n)
    double result = 1.0;
    
for (int i = 0; i < exponent; ++i)
        result *= base;
    
return result;
}

double Power(double base, int exponent)
{
    g_bValid = 
true;
    
if(Equal(base, 0.0))
    {
        
if (exponent < 0)
        {
            g_bValid = 
false;
        }
        
return 0.0;
    }

    
unsigned int absExponent = (unsigned int)exponent;
    
if (exponent < 0)
        absExponent = (
unsigned int)(-exponent);

    
double result = PowerWithUnsignedExponent(base, absExponent);
    
if (exponent < 0)
        result = 
1.0 / result;

    
return result;
}

其时间复杂度为O(n),如何进一步改进?

我们可以用如下公式求a的n次方,其时间复杂度为O(lgn):

n is even: a^n = a^(n/2)*a^(n/2)

n is odd: a^n = a^((n-1)/2)*a^((n-1)/2) * a

改进后代码如下:

【代码2】

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 

/*
n is even: a^n = a^(n/2)*a^(n/2)
n is odd: a^n = a^((n-1)/2)*a^((n-1)/2) * a
*/

double PowerWithUnsignedExponent2(double base, unsigned int exponent)
{
    
// T(n) = O(lgn)
    if (exponent == 0)
        
return 1;
    
else if (exponent == 1)
        
return base;

    
double result = PowerWithUnsignedExponent2(base, exponent >> 2);
    result *= result;

    
if (exponent & 0x1)
    {
        
// exponent is odd
        result *= base;
    }
    
return result;
}

【参考】

http://zhedahht.blog.163.com/blog/static/254111742009101563242535/