leetcode 50: 快速幂(非递归与递归)

题解

  • 题意:实现函数pow(x,n),其中x是double类型,n是int类型(n是)
    • 除了快速幂算法之外,还要注意int类型的正负号取值范围不一样。
  • 题解:快速幂算法(分治思想)
    • 举两个例子,求 x 64 x^{64} x64, 和 x 10 x^{10} x10
      • x 2 = ( x ∗ x ) → x 4 = ( x 2 ) ∗ ( x 2 ) → x 8 = ( x 4 ) ∗ ( x 4 ) ∗ x → x 16 = x 8 ∗ x 8 → x 32 = x 16 ∗ x 16 → x 64 = x 32 ∗ x 32 x^2 = (x*x)\to x^4 = (x^2)*(x^2) \to x^8 = (x^4)*(x^4)*x \to x^{16} = x^{8}*x^8 \to x^{32} = x^{16}*x^{16}\to x^{64} = x^{32}*x^{32} x2=(xx)x4=(x2)(x2)x8=(x4)(x4)xx16=x8x8x32=x16x16x64=x32x32,6次操作
      • x 2 = x ∗ x → x 4 = ( x 2 ∗ x 2 ) → x 8 = ( x 4 ) ∗ ( x 4 ) → x 10 = ( x 2 ) ∗ ( x 8 ) x^2=x*x\to x^4 = (x^2*x^2)\to x^8 = (x^4)*(x^4)\to x^{10}=(x^2)*(x^8) x2=xxx4=(x2x2)x8=(x4)(x4)x10=(x2)(x8),4次操作
    • 可以看到,其实求幂的复杂度可以缩减为 o ( l o g 2 n ) o(log_2 n) o(log2n),从复杂度上来看,可以推测快速幂就是对指数进行分治
    • 上面的步骤是怎么来的呢?
      • 如果n2^x,那么过程很好理解,就是每次划分都只需要求一半数据n/2,另一半翻倍即可,换成二进制就是64=1000000,等价于1左移6位。
      • 如果n不是,那就转换为2^x和另一部分,以此类推,那这其实和二进制串计算的过程完全吻合,比如10=1010,那么计算的过程中,就是看成1000+0010,等价于1左移1位加上1左移3位,再举个例子,15=1111,那么就是 1000 + 0111 → 1000 + 0100 + 0011 → 1000 + 0100 + 0010 + 0001 1000+0111 \to 1000 + 0100 + 0011 \to 1000 + 0100 + 0010 + 0001 1000+01111000+0100+00111000+0100+0010+0001
  • 实现:实现的过程中,我们需要有两个变量,一个从1开始,不断计算当前位对应的值,另一个则累加1出现的位置的值,不过这都是指数层面的运算,换成实际数据,要对操作进行升级(加法变乘法)
  • 非递归
class Solution {
    public double myPow(double x, int n) {
        long d = n;
        double res = 1, tmp = x;
        if(n<0) d=-d;
        while(d!=0){    
            if((d&1)>0)
                res = tmp*res;
            tmp = tmp * tmp;
            d>>=1;
        }
        return n>0?res:1.0/res;
    }
}
  • 递归,来自leetcode题解,不过这个空间复杂度高一些,因为递归函数占用了栈空间
	class Solution {
	    public double quickMul(double x, long N) {
	        if (N == 0) {
	            return 1.0;
	        }
	        double y = quickMul(x, N / 2);
	        return N % 2 == 0 ? y * y : y * y * x;
	    }
	
	    public double myPow(double x, int n) {
	        long N = n;
	        return N >= 0 ? quickMul(x, N) : 1.0 / quickMul(x, -N);
	    }
	}

题目

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值