这是我参与8月更文挑战的第17天,活动详情查看:8月更文挑战
前言
力扣第五十题 Pow(x, n) 如下所示:
实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn)。
示例 1:
输入: x = 2.00000, n = 10
输出: 1024.00000
示例 2:
输入: x = 2.10000, n = 3
输出: 9.26100
示例 3:
输入: x = 2.00000, n = -2
输出: 0.25000
解释: 2-2 = 1/22 = 1/4 = 0.25
一、思路
这一题题目还是比较好理解的,就是实现一个 求n次幂的函数。
我看到这题之后想的是使用递归来实现,但是当 N = 2147483647 很容易就栈溢出了。
伪代码如下所示(每次次方+1):
public double myPow(double x, int n) {
return n > 0 ? dfs(x, x, n) : 1/dfs(x, x, -n);
}
public double dfs(double x, double p, int n) {
if (Math.abs(n) == 1)
return x;
return dfs(x * p, p,n-1);
}
那么如何优化呢?怎么样可以有效的减少递归的层数呢?
答案是:分治算法
分治算法的思路就是将问题向下分解,如二分法
分治 + 递归 的大致的步骤如下所示:
- 如果当前层无法处理,就分解,并向下递归
- 如当前处理的次方为
1,则开始向上回溯
举个例子
此处以 x = 2.0, n = 10 作为例子
- 递归1:
2的10次方解决不了,向下分解为n = 10/2 = 5 - 递归2:
2的5次方解决不了,向下分解为n = 5/2 = 2 - 递归3:
2的2次方解决不了,向下分解为n = 2/2 = 1 - 递归4:
2的1次方有解,向上回溯结果2 - 递归3:向上回溯结果
2 * 2 = 4 - 递归2:向上回溯结果
4 * 4 * 2 = 32 - 递归1:向上回溯结果
32 * 32 = 1024 - 返回结果
1024即可
综上所述,整个分解的过程为 n^10 -> n^5 -> n^2 -> n^1
二、实现
实现代码
实现代码与思路保持一致
public double myPow(double x, int n) {
// 特殊情况
if (x == 0 || x == 1)
return x;
if (n == 0)
return 1;
return n > 0 ? quickMul(x, n) : 1/quickMul(x, -n);
}
public double quickMul(double x, long N) {
if (Math.abs(N) == 1) // 特殊情况:N可能会为-2147483648
return x;
double y = quickMul(x, N / 2);
return N % 2 == 0 ? y * y : y * y * x;
}
测试代码
public static void main(String[] args) {
double ret = new Number50().myPow(2.0, 10);
System.out.println(ret);
}
结果
三、总结
感谢看到最后,非常荣幸能够帮助到你~♥