140. Fast Power (快速幂取模算法)

    今天刷lintcode的时候发现了一道简单的题目,本来没留意很快就写完了,但是提交的时候发现有些测试用例通不过,总是超时,于是明白这道题应该在改进时间复杂度上下功夫,因此总结如下。

题目描述如下:

Calculate the an % b where a, b and n are all 32bit integers.

Example

For 231 % 3 = 2

For 1001000 % 1000 = 0

未考虑时间复杂度的算法:

思想:

    由于a, b, n都是int型,要考虑溢出的情况,因此只需要在循环内部每次乘法运算的时候都进行mod运算即可。 

代码:

class Solution {
public:
    /**
     * @param a: A 32bit integer
     * @param b: A 32bit integer
     * @param n: A 32bit integer
     * @return: An integer
     */
    int fastPower(int a, int b, int n) {
        long long res = 1;
        if(n==0)
            return 1%b;
        for(int i=0; i<n; i++)
            res = (res*a)%b;
        return res;
    }
};

    如果按照这种写法,可以运行,但是当n比较大的时候,无法通过测试用例,时间复杂度为O(n)。

考虑时间复杂度的算法:

思想:

    需要提高时间复杂度,我想起了学习密码学的时候求解幂取模运算时候使用的方法。假如求 x ^ n 次方,首先将n转化为2进制的形式,然后我们可以把 n 表示为 2^k1 + 2k2  + 2^k3....,这样所有数都可以用前式来表示。那么 x^n = x^2^k1 * x^2^k2 * x^2^k3.....那么就可以利用二进制来加快计算速度了。

    假如 x^19 , 22转化为二进制为 10011, 即 x^19 = x^16 * x^2 * x^1;

    这个时候就已经很清晰了。此时的时间复杂度为O(log(n)),可以通过题库的测试用例。

代码:

class Solution {
public:
    /**
     * @param a: A 32bit integer
     * @param b: A 32bit integer
     * @param n: A 32bit integer
     * @return: An integer
     */
    int fastPower(int a, int b, int n) {
        int res = 1;
        long long tmp = a;
        if(n==0)
            return 1%b;
        while(n>0){
            if(n&0x1)
                res = (res*tmp)%b;
            tmp = (tmp*tmp)%b;
            n >>= 1;
        }
        return res;
    }
};

总结:

    很多看似很简单的题目其实需要多思考,和平时学到的东西联系起来,即使第一种方法能通过测试用例,也最好不要使用,因为这样会带来不必要的时间开销。


       





    

阅读更多
相关热词
换一批

没有更多推荐了,返回首页