求num的N次方常规解法是,使用一个for循环,让num*num执行N次,但该算法的时间复杂度为O(N)
1. 思路分析
求num的N次方可以利用二进制的形式进行计算。
例:假设求2的75次方,拆分表示为: 275 = 264 * 28 * 22 * 21。
二进制的形式为201001011,只有当二进制位为1的时,才会带入结果进行计算。
所以我们不妨使用一个临时变量temp代表20,21,22…,264,010010011每次计算左移一位,然后&1,若==0,表示该二进制位为0,不参与计算,若为1,则带入结果进行计算。
2. 时间复杂度分析
常规方法;
public static Integer increment(Integer num,Integer n){
Integer res = 1;
for (int i = 0; i < n; i++) {
res = res*num;
}
return res;
}
res计算了N次,其时间复杂度为:O(N)。
优化方法:
public static Integer pow(Integer num,Integer p){
Integer res = 1;
Integer temp = num;
//p>>=1即p右移一位赋值给p
for(;p!=0;p>>=1){
if((p&1)!=0){
res = product(res,temp);
}
temp = product(temp,temp);
}
return res;
}
public static Integer product(Integer m1, Integer m2){
return m1*m2;
}
在该方法中,temp自增大致计算了logN次,例如:p=75=01001011,for只会执行7次,二进制右移7次后便为0,也就是说,temp*temp也只会执行7次,即使算上带入结果集的计算,只有当最后一位进制为1时才会带入计算,这个时间消耗为M,该方法的时间复杂度忽略常数项M,即为O(logN)。
3. 后言
在Java.lang.Math中pow(double a, double b)方法的实现思路正是该优化方式的思路。