最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java實(shí)現(xiàn)快速冪算法詳解

 更新時(shí)間:2022年10月14日 08:58:51   作者:碼農(nóng)研究僧  
快速冪是用來(lái)解決求冪運(yùn)算的高效方式。此算法偶爾會(huì)出現(xiàn)在筆試以及面試中,特意花時(shí)間研究了下這題,感興趣的小伙伴快跟隨小編一起學(xué)習(xí)一下

前言

此算法偶爾會(huì)出現(xiàn)在筆試以及面試中,特意花時(shí)間研究了下這題

題目:

求AB次方,并且保留最后幾位數(shù)字(此題保留最后3位數(shù))

例子:

21000,輸出的結(jié)果保留3位數(shù)字

在筆試或者面試中看到此題,第一思路可能通過(guò)遞歸或者while遍歷的想法,但細(xì)想一下,這么大的數(shù)字編程語(yǔ)言中任何一個(gè)變量或者計(jì)算機(jī)硬件機(jī)器也hold不住這么大的數(shù)字存儲(chǔ)(越往后冪次越大,總是會(huì)溢出)

此時(shí)想到了海量數(shù)據(jù)如何存儲(chǔ):海量數(shù)據(jù)處理的高頻面試題分析

那我就選擇布隆過(guò)濾器:布隆過(guò)濾器的原理和實(shí)現(xiàn)詳細(xì)分析(全)。(但可能會(huì)有誤差)

硬件無(wú)法存儲(chǔ),那我就分片切片,甚至二進(jìn)制移位來(lái)對(duì)應(yīng)計(jì)算(但是我是21000次方,每一次的冪算,我都整這么復(fù)雜,這計(jì)算一個(gè)數(shù)字要花大半天??)

冷靜思考后,我發(fā)現(xiàn)想復(fù)雜了,應(yīng)該從數(shù)學(xué)推導(dǎo)公式下手,才能提高算法的優(yōu)化

以下章節(jié)對(duì)應(yīng)算法復(fù)雜度的優(yōu)化

1. 暴力算法(fail)

算法如下:

/* 
* base 為底數(shù)
* power 為指數(shù)
*/
public long slowPower(long base,long power){
    long result = 1;
    
    // 依次通過(guò)for循環(huán),將其對(duì)應(yīng)的數(shù)字乘
    for(int i = 1 ;i <= power;i++){
        result *= base;
    }
    
    // 保留最后的3位數(shù)字,求余1000
    return result % 1000;
}

或者使用while循環(huán)

public long slowPower(long base,long power){
    long result = 1;
    
    while(power--){
        result *= base;
    }
    return result % 1000;
}

此處的代碼執(zhí)行的時(shí)候,就會(huì)出現(xiàn)數(shù)組越界

冪次運(yùn)算,越到最后,爆炸式的增長(zhǎng):

對(duì)此求余是最好的想法(因?yàn)閿?shù)值很大保留最后幾位即可)

但數(shù)值本身就已經(jīng)越界,而且爆炸增長(zhǎng)也算不到最后的數(shù)值,更不用提及求余

2. 優(yōu)化取模運(yùn)算(accept)

從上面的理論可得知,在求到某一步的時(shí)候,數(shù)值已經(jīng)越界,那可以提前求余在計(jì)算么

那就要從取模運(yùn)算進(jìn)行深入了解:取模運(yùn)算百度百科

本身模運(yùn)算與基本四則運(yùn)算相似

  • (a + b) % p = (a % p + b % p) % p
  • (a - b) % p = (a % p - b % p ) % p
  • (a * b) % p = (a % p * b % p) % p
  • a ^ b % p = ((a % p)^b) % p

其他的重要的也可提前過(guò)一遍(哪天用得上)

結(jié)合律:

  • ((a+b) % p + c) % p = (a + (b+c) % p) % p
  • ((ab) % p * c)% p = (a * (bc) % p) % p

分配律:

  • (a+b) % p = ( a % p + b % p ) %p
  • ((a +b)% p * c) % p = ((a * c) % p + (b * c) % p) % p

特別是這個(gè)公式:(a * b) % p = (a % p * b % p) % p

算法如下:

/* 
* base 為底數(shù)
* power 為指數(shù)
*/
public long fastPower(long base,long power){
    long result = 1;
    
    // 依次通過(guò)for循環(huán),將其對(duì)應(yīng)的數(shù)字乘
    for(int i = 1 ;i <= power;i++){
        result *= base;
        result %= 1000;
    }
    
    // 保留最后的3位數(shù)字,求余1000
    return result % 1000;
}

3. 優(yōu)化時(shí)間復(fù)雜度(accept)

上面的計(jì)算是21000,如果是210000000000000000000000000000那時(shí)間復(fù)雜度隨著指數(shù)的增加而增加,而且迭代的次數(shù)也特別多,那優(yōu)化時(shí)間復(fù)雜度么?

通過(guò)冪次的巧妙處理,將其冪次計(jì)算的迭代減少

具體如下:(計(jì)算210

pow(2,10)
= pow(4,5)
= pow(4,4) * pow(4,1)
= pow(16,2) * pow(4,1)
= pow(256,1) * pow(4,1)

  • 冪次為偶數(shù),直接處理
  • 冪次為奇數(shù),拆1 以及 偶數(shù)

知道所有的指數(shù)都變?yōu)?,將其相乘即為最終的結(jié)果

最終的算法:

/* 
* base 為底數(shù)
* power 為指數(shù)
*/
public long fasterPower(long base,long power){
    long result = 1;
    
    // 保證指數(shù)大于0 遍歷
    while (power > 0) {
    
        // 偶數(shù)
        if (power % 2 == 0) {
            // 指數(shù)減半
            power /= 2;
            // 底數(shù)平方,記得 (模的運(yùn)算優(yōu)化)
            base = base * base % 1000;
            
        } else {
            // 指數(shù)為奇數(shù)
            // 拆分為1 和 偶數(shù)
            power -= 1;
            
            // result乘底數(shù) 求余 并且放在result(提前存儲(chǔ))
            result = result * base % 1000;
            
            // power偶數(shù),再操作一次
            // 底數(shù)平方,記得 (模的運(yùn)算優(yōu)化)
            power /= 2;
            base = base * base % 1000;
        }
    }
    
    // 直接輸出結(jié)果,已經(jīng)不用求余了
    return result;
}

通過(guò)上面的算法發(fā)現(xiàn)冗余復(fù)雜了,提取公共部分合并

/* 
* base 為底數(shù)
* power 為指數(shù)
*/
public long fasterPower(long base,long power){
    long result = 1;
    
    // 保證指數(shù)大于0 遍歷
    while (power != 0) {
    
        // 奇數(shù)特殊判斷
        if (power % 2) {
            result = result * base % 1000;
        } 
       
        // 再次操作一次,底數(shù)平方,記得 (模的運(yùn)算優(yōu)化)
        // 此處之所以不用減1,是因?yàn)?power 會(huì)向下取整 ,5 / 2 = 2 
        power /= 2;
        base = base * base % 1000;
     
    }
    
    // 直接輸出結(jié)果,已經(jīng)不用求余了
    return result;
}

4. 優(yōu)化 位運(yùn)算(accept)

除2(右移),可以使用移位來(lái)計(jì)算

// 非遞歸
public long fastestPower(long base,long power){
    long result = 1;
    
    while (power != 0) {
    
        // 奇數(shù)特殊判斷
        if (power & 1) {
            result = result * base % 1000;
        } 
       
        power >>= 1;
        base = base * base % 1000;
     
    }
    
    // 直接輸出結(jié)果,已經(jīng)不用求余了
    return result;
}

通過(guò)上面的層層遞進(jìn)進(jìn)行優(yōu)化,自然也可用遞歸

// 遞歸
public long fastestPower(long base,long power){
    if(power == 0) {
        return 1;
    }
    
    return fastestPower(base * base, power >> 1) * (power & 1 == 1 ? base : 1);
}

以上就是Java實(shí)現(xiàn)快速冪算法詳解的詳細(xì)內(nèi)容,更多關(guān)于Java快速冪算法的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論

邹平县| 日照市| 花莲市| 崇左市| 呼玛县| 静宁县| 贺兰县| 武城县| 崇明县| 西峡县| 江城| 洪湖市| 银川市| 馆陶县| 张家港市| 金秀| 南昌市| 无为县| 睢宁县| 安图县| 定兴县| 肃北| 高碑店市| 长沙县| 南漳县| 南乐县| 沭阳县| 莱阳市| SHOW| 名山县| 浦东新区| 苗栗县| 习水县| 敦化市| 资源县| 庄河市| 阳山县| 托里县| 犍为县| 贡山| 南通市|