链接:
https://leetcode.com/problems/powx-n/
大意:
给定一个double型的x,以及一个整数n。求x^n。从他的例子可以看到:保留的是5位小数,也就是说0.000001将会被转成0... 例子:
思路:
采用分治以及递归的思想解决,思想与之前的一个题解求两数的商:https://blog.youkuaiyun.com/smart_ferry/article/details/88740052 类似,具体思路看代码注释
代码:
class Solution {
public double myPow(double x, int n) {
// x为1或0的两种特殊情况
if (x == 1 || x == 0)
return x;
// x == -1 并且 n为偶数的情况
if (x == -1 && n % 2 == 0)
return 1;
// x == -1 并且 n为奇数的情况
if (x == -1 && n % 2 != 0)
return -1;
// n为非负数的情况
if(n >= 0)
return helper(x, n, 1, true);
else
return 1 / helper(x, -(long)n, 1, false);
}
// positive记录原给定的n为正还是负,用于快速跳出迭代计算 这里的n为long型是为了确保在myPow中n为Integer.MIN_VALUE时取反不溢出
public double helper(double x, long n, double curV, boolean positive) {
if (n == 0)
return curV;
int curN = 0;
double curX = x;
while (curN * 2 + 1 <= n) {
curV *= curX;
// 在计算时,如果发现所给次数为正并且当前得到的值的绝对值已经比0.00001小,则直接返回该值
if (positive && Math.abs(curV) < 0.00001)
return 0;
// 在计算时,如果发现所给次数为负并且当前得到的值的绝对值已经比100000小(因为例子是给了5位小数....),则返回Double.MAX_VALUE
if (!positive && Math.abs(curV) > 100000)
return Double.MAX_VALUE;
// curX每次变为原来的平方时,curV就已经乘了x^(2^(curN + 1) - 1)
// 比如 一开始 curV = 1,curN = 0,curX = x
// 则一次迭代之后, curV = x(相比与一开始的1,乘了 x^1) curX = x ^ 2 curN = 1
// 下一次迭代后, curV = x * x^2 = x ^ 3(相比于一开始的1,乘了x^3) curX = x ^ 4 curN = 2
// 再下一次迭代, curV = x ^ 3 * x ^ 4 = x ^ 7 (相比于一开始的1,乘了x^7) curX = x ^ 8 curN = 3
curX *= curX;
curN = curN * 2 + 1;
}
return helper(x, n - curN, curV, positive); // 消除尾递归 提升程序效率
}
}
结果:
结论:
这个题目除了需要想到使用分治+递归的方法之外,还得考虑各种边界情况以及更早跳出循环的条件,另外还得考虑最小整数取绝对值后溢出的问题。