小知识,大挑战!本文正在参与「程序员必备小知识」创作活动。
问题
数值的整数次方
实现 pow(x, n) ,即计算 x 的 n 次幂函数。不得使用库函数,同时不需要考虑大数问题。
力扣链接
考察要点
考察我们对于幂运算以及递归思想的使用
学会将递归思想转换为循环思想解题
思路1
通过for循环来实现, 依次将结果值乘以基数x, 执行n次
时间复杂度为O(n)
缺点: 没有考虑基数为0, 指数为负数的情况
代码1
public double myPow(double x, int n) {
double res = 1;
for (int i = 0; i < n; i++) {
res *= x;
}
return res;
}
思路1 - 改进版
对于基于进行判断, 如果基数为0, 则直接返回0
对于指数进行判断, 如果为负数, 要进行相应的处理
代码1 - 改进版
public double myPow(double x, int n) {
if (x == 0) {
return 0;
}
if (x == 1) return 1;
double res = 1;
// 判断指数n的正负
for (int i = 0; i < (n < 0 ? -n : n); i++) {
res *= x;
}
// 判断指数n的正负
return (n < 0 ? (1 / res) : res);
}
思路2 - 递归方式
假如求3的8次方
那就相当于求 ((3的4次方)的平方)
也就相当于求 (((3的2次方)的平方)的平方)
如果n为奇数数, 那么结果再乘以基数x就好
缺点: 如果指数n很大的情况下, 会导致栈溢出
代码2 - 递归方式
public double myPow(double x, int n) {
// 如果基数x为0, 那么指数为负数的话应该判定错误的输入
if (x == 0) {
return 0;
}
double res = 1;
int abs = n > 0 ? n : -n;
// 如果指数n为负数, 则要对结果进一步处理
return (n > 0 ? power2(x, abs) : (1 / power2(x, abs)));
}
public double power(double x, int n) {
// 递归基
if (x == 0) return 0;
if (n == 1) return x;
// 求x的n次方, 相当于求x的n/2次方的结果, 再进行平方
double res = power(x, n >> 1);
// 对x的n/2次方结果再进行平方
res *= res;
// 如果n为奇数, 结果要再乘以基数x
if ((n & 1) != 0) {
res *= x;
}
return res;
}
思路3 - 循环方式
基于公式
如果指数n为偶数 xn = (x2)n/2
如果指数n为奇数 xn = (x2)n/2 * x
代码3 - 循环方式
public double myPow(double x, int n) {
// 如果基数x为0, 则直接返回0
if (x == 0) return 0;
double res = 1;
if (n < 0) {
x = 1 / x;
n = -n;
}
while (n > 0) {
// 当n为奇数时, 将基数乘入结果res中
if ((n & 1) != 0) res *= x;
// 现在问题就变成了求(x的平方)的(n / 2)问题
// 比如: 求3的8次方, 现在就变成了求9的4次方问题
n >>= 1;
x *= x;
}
return res;
}
总结
通过本题我们可以更深入的了解求幂问题, 对于基数0和指数为负的时候的条件判断. 对于递归的使用, 以及将递归转换为循环的思想. 考察我们的思考严谨性以及对于负面数据的处理问题.