Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

快速幂 #130

Open
TieMuZhen opened this issue Mar 16, 2022 · 0 comments
Open

快速幂 #130

TieMuZhen opened this issue Mar 16, 2022 · 0 comments
Labels

Comments

@TieMuZhen
Copy link
Owner

快速幂(Exponentiation by squaring,平方求幂)是一种简单而有效的小算法,它可以以O(log n)的时间复杂度计算乘方。快速幂不仅本身非常常见,而且后续很多算法也都会用到快速幂。

让我们先来思考一个问题:7的10次方,怎样算比较快?

方法1: 最朴素的想法,77=49,497=343,... 一步一步算,共进行了9次乘法。

这样算无疑太慢了,尤其对计算机的CPU而言,每次运算只乘上一个个位数,无疑太屈才了。这时我们想到,也许可以拆分问题。

方法2: 先算7的5次方,即77777,再算它的平方,共进行了5次乘法。

但这并不是最优解,因为对于“7的5次方”,我们仍然可以拆分问题。

方法3: 先算77得49,则7的5次方为4949*7,再算它的平方,共进行了4次乘法。

模仿这样的过程,我们得到一个在O(log n)时间内计算出幂的算法,也就是快速幂。

递归快速幂

刚刚我们用到的,无非是一个二分的思路。我们很自然地可以得到一个递归方程:

递归快速幂的思路非常自然,代码也很简单(直接把递归方程翻译成代码即可):

function qpow(a, n) {
    if(n == 0){
        return 1;
    }else if(n % 2 == 1){
        return qpow(a, n - 1) * a;
    }else {
        let tmp = qpow(a, n/2);
        return tmp * tmp;
    }
}

注意,这个tmp变量是必要的,因为如果不把qpow(a, n/2)记录下来,直接写成qpow(a, n /2)*qpow(a, n /2),那会计算两次qpow(a, n/2),整个算法就退化为了 O(n)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant