zoukankan      html  css  js  c++  java
  • 快速求幂:快速幂算法

    快速幂,就是快速算底数的n次幂。其时间复杂度为 O(logN), 与朴素的O(N)相比效率有了极大的提高。

    朴素算法

    在要求算出一个数字的n次幂时,最容易想到的便是朴素的循环累乘:

    int normalPower(int base, int exponent) {
        while (exponent > 0) {
            base *= base;
            --exponent;
        }
        return base;
    }
    

    很明显,这种方法的时间复杂度为O(N);

    快速幂算法

    根据二进制的性质以及编程语言中方便的与运算符&和移位运算符>>,有人提出了快速幂的算法,其时间复杂度为O(logN)。对这两个操作符不明白的同学可以先看文末的简述。
    1.快速幂思想
    例如计算ab这样一个数,我们指数b以转换二进制的形式进行分解,将其写成二进制中每一位乘上该位的权重(从右往左,第i位的权为2i-1)。
    例如:a13 = a2^0+2^2+2^3 = a2^0a2^2a2^3
    2.快速幂实现
    在这里我们先给出快速幂实现的代码,方便后续进行对照讲解

    int fastPower(int base, int exponent) {
        int sum = 1;
        while (exponent != 0) {
            if ((exponent & 1) != 0) {
                sum *= base;
            }
            exponent = expnonent >> 1;  // 对指数进行移位
            base *= base;               // 让base的次幂以2的倍数增长
        }
        return sum;
    }
    

    需要额外注意的是,&操作符的运算符低于>之类的比较运算符,也低于==!=运算符。
    3.快速幂讲解
    首先可以看到,循环的终止条件为指数e为0,且每次循环e都会右移一位,而自然数N的二进制长度为log2N,因此这个循环至多遍历log2N次。即它的时间复杂度为O(logN)
    我们在每次指数右移的同时,让底数base=base*base。这样一来,第一次循环结束后base的大小变为原来的2=21次方倍,第二次后变为原来的21*21=22次方倍...最终,我们在第n次循环中sum所乘的base总是base2^(n-1)。保证了算法的正确性。而每次base2^(n-1),总能在下一次的循环中利用到base2^n的计算中,减少了程序的时间消耗与空间消耗。
    假设我们输入了fastPower(bbasese, 13)这样一个函数,那么按照上面的定义,13应该是被理解为二进制串1101,在每次开始都进行和1相与,为1时才进行sum和bbasese的相乘,联系上一段话,我们不难推断出我们能够按照base13 = base2^0+2^2+2^3 = base2^0base2^2base2^3的顺序计算。


    快速幂预备知识
    1.二进制
    相信大家都知道二进制的原理,这里我们主要用到十进制与二进制相互转换的原理。
    举个例子,6的二进制是110,那么6便可以标示成22+21
    2.与运算符&
    这是一个二元运算符,返回左右两数以二进制形式相与后的结果。例如x & 1 == 1则表示x为奇数,x & 1 == 0则为偶数。
    3.移位运算符>>
    顾名思义,这是令一个数的二进制形式移位的操作符。该操作符指向右边,因此是右移,例如1011>>1 = 101。相似的,还有左移用的操作符<<,不过这里用不上。

  • 相关阅读:
    C++设计模式 ==> 装饰(者)模式
    基于路由器的VRRP技术--VRRP的应用
    基于路由器的VRRP技术--VRRP的应用
    C++设计模式 ==> 策略模式与简单工厂模式结合
    C++设计模式 ==> 简单工厂模式
    DVWA之Insecure Captcha
    DVWA之Insecure Captcha
    DVWA之File Inclusion
    DVWA之File Inclusion
    DVWA之XSS
  • 原文地址:https://www.cnblogs.com/Bylight/p/10538891.html
Copyright © 2011-2022 走看看