Leetcode-50 pow(x,n)
题目描述
实现 pow(x, n) ,即计算 x 的 n 次幂函数。
示例 1:
输入: 2.00000, 10
输出: 1024.00000
示例 2:
输入: 2.10000, 3
输出: 9.26100
示例 3:
输入: 2.00000, -2
输出: 0.25000
解释: 2-2 = 1/22 = 1/4 = 0.25
说明:
-100.0 < x < 100.0
n 是 32 位有符号整数,其数值范围是 [−2^31, 2^31 − 1] 。
自己的方法
1、
class Solution {
public double myPow(double x, int n) {
return Math.pow(x,n);
}
}
运行通过
2、迭代法
class Solution {
public double myPow(double x, int n) {
if(n==0)
return 1;
int i=n;
if(n<0)
i=-n;
double result=1;
while(i!=0)
{
result=result*x;
i--;
}
if(n<0)
return 1/result;
else
return result;
}
}
运行结果:
最常见的运行时限是1秒,即时间复杂度不能超过一千万(10000000,八位数),但一般对空间不会做太大的要求,所以一般都选择以空间换时间
显然当n等于INT_MAX时会超出时间限制
3、递归法
class Solution {
public double myPow(double x, int n) {
if(n==0)
return 1;
else if(n<0)
return (1/x)*(1/myPow(x,-n-1));
else
return x*myPow(x,n-1);
}
}
运行结果:
发生栈内存溢出错误
重点
1、n为负数时,取pow(x,-n)的倒数即可
2、因此只需要考虑n为自然数(大于等于0)的情况
3、快速幂算法:以2为基础,而不是1,这样x^64只需要6次计算就可以得到,而不需要计算63次,大大减少了计算时间
本质是分治思想
要计算x^64,可以按照以下顺序:
要计算x^77,可以按照以下顺序:
在
这些步骤中,我们直接把上一次的结果进行平方,
而在
这些步骤中,我们把上一次的结果进行平方后,还要额外乘一个 x。因此
4、应该是
而不应该是
所以应该从右向左分析,而不是从左向右分析
官方答案
1、快速幂算法+递归
class Solution {
public double myPow2(double x,long n)//只考虑n大于等于0的情况
{
if(n==0)
return 1.0;
double y=myPow2(x,n/2);
if(n%2==0)
{
return y*y;
}
else
{
return y*y*x;
}
}
public double myPow(double x, int n) {
long N=n;
if(n>=0)
return myPow2(x,N);
else
return 1.0/myPow2(x,-N);
}
}
注:
1、n要转换为long类型,否则会发生溢出,因为n为INT_MIN时为负数,当转为-n时会比INT_MAX大1,发生溢出
2、要记录myPow2(x,n/2)的值,否则会超出时间限制
2、快速幂算法+迭代
举个例子,要求x^77,首先将77转化为二进制1001101,每一位1分别对应1、4、8、64,因此使用就可以计算出 x^77 的值。注意中间是用*连接的,不是用+连接的
class Solution {
public double myPow2(double x,long n){
if(n==0)
return 1.0;
double num=x;
double result=1.0;
while(n!=0)
{
if(n%2==1)
{
result*=num;
}
num*=num;//这一步很巧妙
n/=2;
}
return result;
}
public double myPow(double x, int n) {
long N=n;
if(n<0)
return 1.0/myPow2(x,-N);
else
return myPow2(x,N);
}
}
使用递归会消耗一部分栈内存
递归存在栈内存溢出隐患