// 时间复杂度为 logn
class Solution {
public double myPow(double x, int n) {
if(x == 1.0 || n == 0){
return 1.0;
}
// 需要将 n转成long格式的N 当n=-2147483648时,-n超出了n的范围
long N = n;
return n < 0 ? 1.0 / quickMul(x,-N): quickMul(x,N);
}
public double quickMul(double x, long N){
if(N == 0){
return 1.0;
}
// 递归下一层
double y = quickMul(x, N/2);
return N % 2 == 1 ? y * y * x : y * y ;
}
}
1、需要注意n可以为负数,-2^31 <= n <= 2^31-1,所以n = -n需要用long,否则会溢出
2、将n转化为2进制
遍历范围:(; n!=0;n>>=1);
当bit上为1时,res = res * x ,此时x是当前bit位对应x的次方
每右移一位,x = x * x,
3、主要使用x^n = x^a + x^b (a+b = n)
class Solution {
public double myPow(double x, int n) {
long t = n;
if (n<0) {
t = -t;
x = 1/x;
}
double res = 1;
while(t>0) {
if ((t&1) != 0) {
res = res * x;
}
x=x * x;
t = t>>1;
}
return res;
}
}
class Solution {
public double myPow(double x, int n) {
long y = n;//int :-2147483648~2147483647否则取相反数会保存不下
double sum = 1;
if(y < 0){
y = -y;
x = 1 / x;
}
while(y != 0){
if(y % 2 == 1){
sum = sum * x;
}
y = y / 2;
x *= x;
}
return sum;
}
}
def myPow(x,n):
res = 1
if n < 0:
n = -n
x = 1 / x
while n > 0:
# 这里也可以用n % 2 == 1
if n & 1 == 1:
res = res * x
x = x * x
# 向右移动一位
n = n >> 1
return res
坑:要用long存n,否则 -2147483648 转正数会溢出,因为 int 范围是 -2147483648 ~ 2147483647
class Solution {
public double myPow(double x, int n) {
boolean ne = false;
long N = n;
if (n < 0) {
ne = true;
N = -N;
}
double ans = 1, t = x;
while (N > 0) {
if ((N & 1) == 1) ans *= t;
t = t * t;
N >>= 1;
}
return ne ? 1.0 / ans : ans;
}
}
class Solution {
public: //分治
double quikmul(double x, long long n){
if(n==0) return 1.0;
double y = quikmul(x,n/2);
return n%2==0?y*y:y*y*x;
}
double myPow(double x, int n) {
long long N = n;
return N>0?quikmul(x,N):1.0/quikmul(x,N);
}
};
class Solution {
public:
double myPow(double x, int n) {
double res = 1;
long m = n;
if(n < 0) {
m = -m;
x = 1/x;
}
while(m > 0) {
if(m % 2 == 1) {
res = res * x;
}
x = x * x;
m = m / 2;
}
return res;
}
};
func myPow(x float64, n int) float64 {
var sum float64
sum = 1
if n < 0 {
n = - n
x = 1 / x
}
tmp := x
for n != 0 {
if n & 1 == 1 {
sum = sum * tmp
}
tmp = tmp * tmp
n = n >> 1
}
return sum
}
class Solution:
def myPow(self, x: float, n: int) -> float:
# 位运算
def QuickMul(n):
ans = 1.0
x_contribute = x
while n > 0:
# 若最低位为1,结果就乘x
if n % 2 == 1:
ans *= x_contribute
# 每进一位都做平方
x_contribute *= x_contribute
# 舍弃n对应二进制数的最低位
n //= 2
return ans
return QuickMul(n) if n >= 0 else 1.0 / QuickMul(-n)
class Solution {
public double myPow(double x, int n) {
return n < 0 ? 1 / getPositiveExponent(x, -n) : getPositiveExponent(x, n);
}
private double getPositiveExponent(double x, long n) {
if (n == 0) {
return 1.0;
}
double temp = getPositiveExponent(x, n / 2);
return n % 2 == 0 ? temp * temp : temp * temp * x;
}
}
实现方式二:迭代+快速幂。时间复杂度O(logN),空间复杂度O(1)。
class Solution {
public double myPow(double x, int n) {
long exponent = n;
if (exponent < 0) {
exponent = -exponent;
x = 1 / x;
}
double res = 1.0;
while (exponent > 0) {
if (exponent % 2 == 1) {
res = res * x;
}
x = x * x;
exponent /= 2;
}
return res;
}
}
class Solution:
def myPow(self, x: float, n: int) -> float:
tem = x
absn= abs(n)
sum=1
while absn:
if absn&1==1:sum *=tem
tem *=tem
absn = absn>>1
return sum if n>0 else 1/sum
class Solution {
public double myPow(double x, int n) {
double res = 1;
long y = n;
if(y<0){
y = -y;
x = 1 / x;
}
while(y>0){
if (y%2==1){
res *= x;
}
x *= x;
y = y/2;
}
return res;
}
}
class Solution {
public double myPow(double x, int n) {
double res = 1;
long m = n;
if(m < 0) {
x = 1/x;
m = -m;
}
while(m > 0) {
if((m & 1) == 1) {
res *= x;
}
x *= x;
m >>= 1;
}
return res;
}
}
class Solution {
public double myPow(double x, int n) {
double sum = 1;
long y = n;
if(y<0){
y = -y;
x =1/x;
}
while(y>0){
if(y%2 == 1){
sum = sum*x;
}
x*=x;
y/=2;
}
return sum;
}
}
class Solution {
public double myPow(double x, int n) {
double res = 1;
long y = n;
if (n < 0) {
y = -y;
x = 1 / x;
}
while (y > 0) {
if (y % 2 == 1) {
res = res * x;
}
x *= x;
y /= 2;
}
return res;
}
}
class Solution {
public:
double quickMul(double x, long long N) {
if (N == 0) return 1.0;
if (N == 1) return x;
double y = quickMul(x, N / 2);
return N % 2 == 0 ? y * y : y * y * x;
}
double myPow(double x, int n) {
long long N = n;
return N >= 0 ? quickMul(x, N) : 1.0 / quickMul(x, -N);
}
};
class Solution {
public double myPow(double x, int n) {
long N = n;
return N >= 0 ? getPow(x,N) : 1.0 / getPow(x,-N);
}
double getPow(double x,long N){
double sum = 1;
double tmp = x;
while(N != 0){
if((N & 1) == 1){
sum *= tmp;
}
tmp *= tmp;
N >>= 1;
}
return sum;
}
}
快速幂 + 递归
每次递归都会使得指数减少一半,因此递归层数为O(logn)
时间/空间复杂度为O(logn)
class Solution {
public double myPow(double x, int n) {
long N = n;
return N >= 0 ? getPow(x,N) : 1.0 / getPow(x,-N);
}
double getPow(double x,long N){
if(N == 0) return 1.0;//0次方为1
double y = getPow(x,N / 2);
return N % 2 == 0 ? y * y : y * y * x;//如果为偶数次方则只需要y*y,如果为奇数次方则还需乘一个x
}
}
class Solution:
def myPow(self, x: float, n: int) -> float:
if x == 0:
return 0
if n < 0:
x, n = 1/x, -n
res = 1
while n:
if n & 1:
res *= x
x *= x
n >>=1
return res
class Solution:
def myPow(self, x: float, n: int) -> float:
# 快速幂的非递归方式,需要注意这道题还有负指数的情况
flag=0
if n<0:
flag=1
n=-1*n
ans=1
while n!=0:
if n&1==1:
ans*=x
x*=x
n=n>>1
if flag==1:
ans=1/ans
return ans
class Solution {
public double myPow(double x, int n) {
double res = 1;
long y = n;
if(n < 0){
y = -y;
x = 1/x;
}
while(y != 0){
if(y % 2 == 1){
res = res * x;
}
x = x*x;
y = y/2;
}
return res;
}
}
共以下 34 个回答
1、需要注意n可以为负数,-2^31 <= n <= 2^31-1,所以n = -n需要用long,否则会溢出
2、将n转化为2进制
遍历范围:(; n!=0;n>>=1);
当bit上为1时,res = res * x ,此时x是当前bit位对应x的次方
每右移一位,x = x * x,
3、主要使用x^n = x^a + x^b (a+b = n)
位运算的思想
快速幂
时间复杂度:O(logn)
空间复杂度:O(1)
时间O(logn) 空间O(1)
时间复杂度:O(logn)
空间复杂度:O(1)
实现方式一:递归求一个数的指数。递归中用一个double型变量存储x的n/2次方结果,才是递归了logN次。时间复杂度O(logN),空间复杂度O(logN)。
实现方式二:迭代+快速幂。时间复杂度O(logN),空间复杂度O(1)。
时间O(logn),空间O(1)
时间复杂度:O(lgN)
先不管n的正负,都变成正的,然后进行计算,输出时判断n的正负,返回sum或1/sum
处理负数的情况
快速幂
本来还在疑惑为什么视频中要用y来代替n,试了一下才发现n是int 的
时间O(logn)
空间O(1)
//快速幂,递归和迭代recursion和iteration
class Solution {
public:
double quickmul(double x,long long n){
double res=1.0;
double mul=x;
while(n>0){
if(n&1){
res=mul;
}
mul=mul;
n/=2;
}
return res;
}
double myPow(double x, int n){
long long k=n;
return n>=0? quickmul(x,k):1.0/quickmul(x,-k);
};
时间:O(log(n)),空间:O(1)
快速幂 + 迭代 时间复杂度O(logn),空间复杂度O(1)
对于快排幂的递归还是有点不是很清楚,需要后面再花时间研究
快速幂 + 迭代
主要问题:用例中n给的超出int的范围,必须转换为long,不然表示的数有差异
时间复杂度O(logn) 即对n进行二进制拆分的复杂度
空间复杂度O(1)
快速幂 + 递归
每次递归都会使得指数减少一半,因此递归层数为O(logn)
时间/空间复杂度为O(logn)
时间复杂度 O(log 2n)
这道题本质上是快速幂算法,快速幂最开始是按照递归方式做的,递归方式很简单,非递归稍微难理解一点,因为需要判断奇偶性,所以引入了位运算
时间复杂度 O(logn)
空间复杂度 O(1)
题目本身而言,还需要注意有负数指数
时间复杂度为O(lgn),空间复杂度为O(1)