这是我参与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);
}
结果
三、总结
感谢看到最后,非常荣幸能够帮助到你~♥