LeetCode 50. Pow(x, n)

Pow(x, n)

实现 pow(x, n) ,即计算 x 的整数 n 次幂函数(即,x^n )。

方法一、快速幂 + 递归

比较容易联想到递归,x的n次方可递归表示为x乘以x的n-1次方。

快速幂的使用:举个🌰,x的20次方,我们为了提高效率,可以用x^10 * x^10表示,类似二分法的思想。
注意:

  • n为负数时取正数结果的倒数即可。
  • 奇数时由于除2,会丢失一个x,因此需要补上。

复杂度分析:
时间复杂度:O(logn)
空间复杂度:O(n)

Swift

func myPow(_ x: Double, _ n: Int) -> Double {
    let N = n
    let res = N > 0 ? quiMul(x, N) : 1/quiMul(x, -N)
    return res
}

func quiMul(_ x:Double, _ n:Int) -> Double {
    if n == 0 {
        return 1
    }
    
    let y = quiMul(x, n/2)//对半劈开,x^4 = x^2 * x^2
    return n % 2 == 0 ? y * y : y*y*x
}

OC

-(double)myPow:(double)x n:(NSInteger)n {
    NSInteger N = n;
    
    return N > 0 ? [self quickMul:x n:N] : 1/[self quickMul:x n:-N];
}

-(double)quickMul:(double)x n:(NSInteger)n {
    if (n == 0) {
        return 1;
    }
    
    double y = [self quickMul:x n:n/2];
    return n % 2 == 0 ?  y*y : x*y*y;
}

方法二、快速幂+迭代法

递归占用了栈空间,那么能否实现一种空间复杂度为1的算法呢?
技巧性较强,需要找到规律。
发现规律
这样以来,我们从 x开始不断地进行平方,得到 x2,x4,x8,x16,⋯, 如果 n的第 k 个(从右往左,从 0 开始计数)二进制位为 1,那么我们就将对应的贡献计入答案。

复杂度分析:
时间复杂度:O(logn)
空间复杂度:O(1)

Swift

func myPow(_ x: Double, _ n: Int) -> Double {
    let N = n
    let res = N > 0 ? quiMul(x, N) : 1/quiMul(x, -N)
    return res
}

//递归法清晰,但是占用了栈空间,因此,我们使用迭代实现
func quiMul(_ x:Double, _ n:Int) -> Double {
    
    var N = n
    var ans:Double = 1.0;
    
    var contribute = x
    while N > 0 {
        if N % 2 == 1 {
            ans *= contribute
        }
        
        //将贡献不断地平方
        contribute *= contribute
        
        N /= 2
    }
    
    return ans
}

OC

-(double)myPow:(double)x n:(NSInteger)n {
    NSInteger N = n;
    
    return N > 0 ? [self quickMul:x n:N] : 1/[self quickMul:x n:-N];
}

-(double)quickMul:(double)x n:(NSInteger)n {
    double x_contribute = x;
    double ans = 1.0;
    while (n > 0) {
        if (n % 2 == 1) {
            ans *= x_contribute;
        }
        
        x_contribute *= x_contribute;
        
        n /= 2;
    }
    return ans;
}
  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jarlen John

谢谢你给我一杯咖啡的温暖

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值