前言
快速幂的迭代和递归实现,练习如何递归分解子问题做到统一操作。
一、Pow(x,n)
二、快速幂
1、递归
//Pow(x,n)
public class MyPower {
//暴力解:一个一个的乘肯定太浪费时间
//问题定义:如何做到快速乘法?
//方案:x的i次方 * x的j次方 = x的i+j次方
//递归思想,x的n次方 = x 的 n/2次方 * x 的 n/2次方 * n是否为偶数?y:1
//Time:O(logN),Space:O(logN)
public double myPow(double x, int n) {
long en = n;//用long防止越界,比统一成负数处理方便。
if (en > 0) return quicklyMul(x, en);
return 1.0 / quicklyMul(x, -en);//负幂次就是正幂次的倒数。
}
private double quicklyMul(double x, long n) {
if (0 == n) return 1.0;
double rs = quicklyMul(x, n / 2);
rs *= rs;
if (1 == (1 & n)) return rs * x;
return rs;
}
}
2、统一负数来考虑边界问题
//不用long防止越界
class MyPower2 {
public double myPow(double x, int n) {
boolean isPositive = n > 0;
if (isPositive) n = -n;//负数表示范围大,统一成负数处理
double rs = quicklyMul(x, (n / 2) * -1);
rs *= rs;
rs *= (1 & n) == 0 ? 1 : x;
if (isPositive) return rs;//统一负数,防止越界
return 1.0 / rs;//负幂次就是正幂次的倒数。
}
private double quicklyMul(double x, int n) {
if (0 == n) return 1.0;
double rs = quicklyMul(x, n / 2);
rs *= rs;
if (1 == (1 & n)) return rs * x;
return rs;
}
}
3、迭代
//一题多解,采用快速幂 + 迭代
class MyPower3 {
//x的i次方 * x的j次方 = x的i+j次方
//将n转化为二进制,每位不为0的二进制数加上不就是n吗,如5 == 0101 == 1 + 4
//Time:O(logN),Space:O(1)
public double myPow(double x, int n) {
long en = n;
if(n < 0) en = -n;
double rs = 1,temp = x;
while (en != 0){
if((en & 1) == 1) rs *= temp;
temp *= temp;
en >>>= 1;
}
if(n > 0) return rs;
return 1.0 / rs;
}
}
总结
1)快速幂
2)递归分解子问题