今天刷lintcode的时候看到一道题,快速求幂的,即求
常规方法是如下:
while(b-- > 0){ a *= a; } return a;
他的复杂度是O(N)。
还有一种更有效率的做法,利用二进制(强大的二进制,如果涉及到int处理,最好先看看能不能使用二进制):
首先,对于任意的int n都有:
那么自然,
其中p(n) = 1或0 是不是感觉很熟悉,从0遍历 到i-1就可以了。。。。
写一下代码就是:
public int power(int a,int n){ if (n == 0) { return 1 ; } if (n == 1) { return a ; } //利用递归方法,递归i-1次计算 int temp = power(a, n >> 1); temp = temp * temp ; if((n & 1) == 1){ temp = temp * a; } return temp; }
代码主要逻辑在这里:
//利用递归方法,递归i-1次计算 int temp = power(a, n >> 1); temp = temp * temp ; if((n & 1) == 1){ temp = temp * a; } return temp;
假设temp = power(a,n>>1)是已经把第j位计算出来了(最开始计算的是第1位的结果),然后下边的代码
temp = temp * temp ; if((n & 1) == 1){ temp = temp * a; } return temp;
是计算第j+1位的结果(最高位是第一位)。if((n & 1) == 1) 这个判断是判断P(n)是否是0。如n=2, 二进制表示为10,那么递归的返回条件里,匹配到这个条件:
if (n == 1) { return a ; }
即temp = power(a,n>>1)这行的第一个返回结果是a,那么在下面
temp = temp * temp ; if((n & 1) == 1){ temp = temp * a; } return temp;
这段代码,是计算10的第二位,即0这位,首先temp = a,那么temp = temp * temp 结果也是a*a,n&1 =0;所以temp = temp * a 不执行; 最终结果是a*a,即n=2的时候,返回结果是a*a。当n更大的时候,同理。
下面是lintcode的140题的代码:
public int fastPower(int a, int b, int n) { // write your code here if (n == 0) { return 1 % b; } if (n == 1) { return a % b; } long temp = fastPower(a, b, n >> 1); temp = temp * temp % b; if((n & 0x1) == 1){ temp = temp * a % b; } return (int)temp; }
需要注意的是这个:long temp = fastPower(a, b, n >> 1); 我刚开始用的是int,结果出错了。。 因为fastPower(a, b, n >> 1);的返回结果可能会超过int的限度,所以我后期改成了long,也算一个小bug。。。