快速冪實現pow函數(從二分和二進制兩種角度理解快速冪)

文章目錄

  • 迭代實現快速冪
    • 思路
      • int的取值范圍
      • 快速冪
        • 從二進制的角度來理解
        • 從二分法的角度來理解
    • 代碼
    • 復雜度分析
  • 進階——超級次方
    • 思路
      • 倒序+快速冪
      • 正序+快速冪
    • 代碼
    • 復雜度分析


迭代實現快速冪

實現 pow(x, n) ,即計算 x 的 n 次冪函數(即,xn)。不得使用庫函數,同時不需要考慮大數問題。

示例 1:

輸入:x = 2.00000, n = 10
輸出:1024.00000

示例 2:

輸入:x = 2.10000, n = 3
輸出:9.26100

示例 3:

輸入:x = 2.00000, n = -2
輸出:0.25000
解釋:2-2 = 1/22 = 1/4 = 0.25

提示:

-100.0 < x < 100.0
-231 <= n <= 231-1
-104 <= xn <= 104


思路

想用累乘處理冪路子就走窄了,超時是板上釘釘的。

用快速冪的思想才符合題目考察的意圖,在詳說快速冪之前說一個很刁鉆的測試用例 —— n=-2147483648

int的取值范圍

我們知道:

  • int的取值范圍是-2147483648-231)到2147483647231 - 1
  • -2147483648有一位符號位可用,因此2147483647是32位操作系統中最大的符號型整型常量。
  • 當出現這個刁鉆的測試用例時,如果對n粗暴的取絕對值的話,int是容納不下的,因此當 n<0 時, 需要定義一個long long類型變量 m 來存儲 n 的絕對值。

快速冪

從二進制的角度來理解

  • 對于任何十進制正整數 n ,設其二進制為在這里插入圖片描述
    則有:

在這里插入圖片描述

  • 根據以上推導,可把計算 xn 轉化為解決以下兩個問題:

在這里插入圖片描述

  • 因此,應用以上操作,可在循環中依次計算在這里插入圖片描述
    的值,并將所有在這里插入圖片描述累計相乘即可。

在這里插入圖片描述
在這里插入圖片描述


從二分法的角度來理解

快速冪實際上是二分思想的一種應用。

  • 二分推導: xn = xn/2 × xn/2 = (x2)n/2,令 n/2 為整數,則需要分為奇偶兩種情況(設向下取整除法符號為 “//” ):

在這里插入圖片描述

  • 冪獲取結果:
  1. 根據二分推導,可通過循環 x = x2 操作,每次把冪從 n 降至 n//2 ,直至將冪降為 0
  2. sum=1 ,則初始狀態 xn = xn × sum。在循環二分時,每當 n 為奇數時,將多出的一項 x 乘入 sum ,則最終可化至 xn = x0 * sum = sum,返回 sum 即可。

在這里插入圖片描述

轉自作者:jyd

算法流程:

  1. x = 0 時:直接返回 0 (避免后續 x = 1 / x 操作報錯)。
  2. 初始化 sum = 1
  3. n < 0 時:把問題轉化至 n≥0 的范圍內,即執行 x = 1/xn = - n
  4. 循環計算:當 n = 0 時跳出;
  • n&1=1 時:將當前 x 乘入 sum(即 sum?=x );
  • 執行 x = x2(即 x?=x );
  • 執行 n 右移一位(即 n>>=1)。
  1. 返回 sum。

代碼

class Solution {
public:double myPow(double x, int n) {if(x == 0) return 0;double sum = 1;long long m = n;if(n < 0){x = 1.0/x;m = -m;}while(m > 0){if(m & 1){sum *= x;}x *= x;m >>= 1;}return sum;}
};

復雜度分析

  • 時間復雜度 O(log_2 n): 二分的時間復雜度為對數級別。
  • 空間復雜度 O(1): sum, b 等變量占用常數大小額外空間。

進階——超級次方

計算 ab1337 取模,a 是一個正整數,b 是一個非常大的正整數且會以數組形式給出。


思路

本題的難點在于對 數組b 的處理,顯然無法將其轉為 一個具體類型,因此解決方法無非就是 在 倒序 or 正序 遍歷數組的同時進行次方處理

倒序+快速冪

本質無非就是把上面提到的二進制思想轉為十進制,具體來說:

223 可以看作 2(10 * 2) + (1 * 3) ,也就是 10242 * 23

那么我們只需要在第 k倒序遍歷 數組 b 的同時,記錄 a 的 10k-1 次方即可。


正序+快速冪

思路源于秦九韶算法,一般地,一元 n 次多項式的求值需要經過 (n+1)?n2\frac{(n+1)*n}{2}2(n+1)?n? 次乘法和 nnn 次加法,而秦九韶算法只需要 nnn 次乘法和 nnn 次加法。大大簡化了運算過程。

把一個 n 次多項式:
在這里插入圖片描述
改寫成如下形式:
在這里插入圖片描述

舉個具體的例子,計算 22342^{234}2234

2234=2200+30+4=2200?230?24=(220?23)10?24=[(110?22)10?23]10?242^{234} = 2^{200+30+4} = 2^{200} * 2^{30} * 2^4 = (2^{20} * 2^3)^{10} * 2^4 = [(1^{10} * 2^2)^{10} * 2^3]^{10} * 2^42234=2200+30+4=2200?230?24=(220?23)10?24=[(110?22)10?23]10?24

最后一步推導實際上是對規律的歸納,即:以 1 作為初始值 res,每次有 新項 加入時,對 res 執行 res=res10?新項res = res^{10} * 新項res=res10? 的操作。


代碼

class Solution {const int MOD = 1337;int quickmul(int x, int n){ // 快速冪實現pow功能if(x == 0) return 0;int sum = 1;while(n){if(n&1) sum = (long)sum * x % MOD;n >>= 1;x = (long)x * x % MOD;}return sum;}
public:int superPow(int a, vector<int>& b) { // 倒序int res = 1, n = b.size();for(int i=n-1; i>=0; i--){res = (long)res * quickmul(a, b[i]) % MOD;a = quickmul(a, 10); // 記錄當前 a 的冪}return res;}int superPow(int a, vector<int>& b) { // 正序int res = 1, n = b.size();for(int i : b){res = (long)quickmul(res, 10) * quickmul(a, i) % MOD;// 加入新項時,對 res 執行 res = res^10 * 新項 的操作}return res;}
};

復雜度分析

  • 時間復雜度O(∑i=0n?1log?bi\sum_{i=0}^{n-1}{\log{b_i}}i=0n?1?logbi?): 其中 n 是數組 b 的長度,對每個 bib_ibi? 計算快速冪的時間為 O(log?bi\log{b_i}logbi?)。
  • 空間復雜度O(1): 過程由迭代實現,避免了遞歸方法對棧空間的占用,只需要常數的空間存放若干變量。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/443799.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/443799.shtml
英文地址,請注明出處:http://en.pswp.cn/news/443799.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

備份MySQL數據庫的命令

備份MySQL數據庫的命令 mysqldump -hhostname -uusername -ppassword databasename > backupfile.sql 備份MySQL數據庫為帶刪除表的格式 備份MySQL數據庫為帶刪除表的格式&#xff0c;能夠讓該備份覆蓋已有數據庫而不需要手動刪除原有數據庫。 mysqldump -–add-drop-…

n位數的全排列(需要考慮大數的情況)

文章目錄題目思路代碼題目 輸入數字 n&#xff0c;按順序打印出從 1 到最大的 n 位十進制數。比如輸入 3&#xff0c;則打印出 1、2、3 一直到最大的 3 位數 999。 示例 1: 輸入: n 1 輸出: [1,2,3,4,5,6,7,8,9] 說明&#xff1a; 用返回一個整數列表來代替打印 n 為正整數 …

正則表達式匹配(動規)

文章目錄題目思路轉移方程特征再探 i 和 j代碼題目 請實現一個函數用來匹配包含 . 和 * 的正則表達式。模式中的字符 . 表示任意一個字符&#xff0c;而 * 表示它前面的字符可以出現任意次&#xff08;含0次&#xff09;。在本題中&#xff0c;匹配是指字符串的所有字符匹配整…

在循環遞增一次的數組中插入元素

文章目錄題目思路如何建立左右區間&#xff1f;如何查找最高點&#xff1f;那我們怎么判斷 num 到底處于什么樣的位置呢&#xff1f;如何確定插入位置&#xff1f;插入元素代碼題目 給一個只循環遞增一次的數組 res&#xff0c;res 滿足首元素大于等于尾元素&#xff0c;形如&…

Unable to find 'struts.multipart.saveDir' property setting.

Unable to find struts.multipart.saveDir property setting. 今天在做工作的時候遇到了這個問題&#xff0c;后來經過百度&#xff0c;終于知道了原因&#xff0c;現在記錄下來&#xff0c;以備以后查看。 1.struts.multipart.saveDir沒有配置 2.struts.multipart.saveDir用…

表示數值的字符串(有限狀態自動機與搜索)

文章目錄題目思路一代碼一思路二代碼二題目 思路一 考察有限狀態自動機&#xff08;參考jyd&#xff09;&#xff1a; 字符類型&#xff1a; 空格 「 」、數字「 0—9 」 、正負號 「 」 、小數點 「 . 」 、冪符號 「 eE 」 。 狀態定義&#xff1a; 按照字符串從左到右的…

樹的子結構

文章目錄題目深搜深搜代碼廣搜廣搜代碼題目 輸入兩棵二叉樹A和B&#xff0c;判斷B是不是A的子結構。(約定空樹不是任意一個樹的子結構) B是A的子結構&#xff0c; 即 A中有出現和B相同的結構和節點值。 例如: 給定的樹 A: 給定的樹 B&#xff1a; 返回 true&#xff0c;因為…

寫題過程中碰見的小問題

文章目錄和--vector二維vector的初始化數組中最大的數max_element()數組所有元素之和accumulate()vector數組去重對pair類型的vector排序對元素都為正整數的vector利用sort默認的升序排列進行降序排列一維數組轉二維數組size_t和int如何不用臨時變量交換兩個數?將類函數的形參…

LeetCode——二叉樹序列化與反序列化

文章目錄題目思路問題一問題二代碼實現題目 請實現兩個函數&#xff0c;分別用來序列化和反序列化二叉樹。 設計一個算法來實現二叉樹的序列化與反序列化。不限定序列 / 反序列化算法執行邏輯&#xff0c;你只需要保證一個二叉樹可以被序列化為一個字符串并且將這個字符串反序…

jsp中生成的驗證碼和存在session里面的驗證碼不一致的處理

今天在調試項目的時候發現&#xff0c;在提交表單的時候的驗證碼有問題&#xff0c;問題是這樣的&#xff1a;就是通過debug模式查看得知&#xff1a;jsp頁面生成的驗證碼和表單輸入的頁面輸入的一樣&#xff0c;但是到后臺執行的時候&#xff0c;你會發現他們是不一樣的&#…

求1~n這n個整數十進制表示中1出現的次數

文章目錄題目思路代碼復雜度分析題目 輸入一個整數 n &#xff0c;求1&#xff5e;n這n個整數的十進制表示中1出現的次數。 例如&#xff0c;輸入12&#xff0c;那么1&#xff5e;12這些整數中包含1 的數字有1、10、11和12。可得1一共出現了5次。 思路 將個位、十位……每位…

求數字序列中的第n位對應的數字

文章目錄題目思路代碼復雜度分析致謝題目 數字以0123456789101112131415…的格式序列化到一個字符序列中。在這個序列中&#xff0c;第5位&#xff08;從下標0開始計數&#xff09;是5&#xff0c;第13位是1&#xff0c;第19位是4&#xff0c;等等。 請寫一個函數&#xff0c…

一學就廢的歸并排序

文章目錄其他與排序有關的文章原理代碼實現復雜度分析其他與排序有關的文章 一學就廢的三種簡單排序【冒泡、插入、選擇】 原理 歸并排序&#xff08;Merge sort&#xff09;&#xff1a; 歸并排序對元素 遞歸地 進行 逐層折半分組&#xff0c;然后從最小分組開始&#xff0c…

神奇的x -x,Lowbit函數的實現方式!

文章目錄-xx & -x&#xff0c;當x為偶數時x & -x&#xff0c;當x為奇數時x&-x 的實際用途-x -x 在二進制里表示對 x 的二進制按位取反(~x)之后再加 1 &#xff0c;即 -x ~x1x & -x&#xff0c;當x為偶數時 在執行 x & -x 時&#xff0c;若 x 為偶數&am…

JAVA實現把指定文件夾下的所有文件壓縮成zip包

1.代碼如下&#xff1a; package cn.gov.csrc.base.util;import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import…

樹狀數組的相關知識 及 求逆序對的運用

文章目錄樹狀數組概念前綴和和區間和樹狀數組原理區間和——單點更新前綴和——區間查詢完整代碼離散化sort函數unique函數去重erase函數僅保留不重復元素通過樹狀數組求逆序對樹狀數組概念 樹狀數組又名二叉索引樹&#xff0c;其查詢與插入的復雜度都為 O(logN)&#xff0c;其…

二叉搜索樹相關知識及應用操作

文章目錄概念查找二叉搜索樹的第k大節點概念 二叉查找樹&#xff08;Binary Search Tree&#xff09;&#xff0c;&#xff08;又名&#xff1a;二叉搜索樹&#xff0c;二叉排序樹&#xff09;——它或者是一棵空樹&#xff0c;或者是具有下列性質的二叉樹&#xff1a; 若它的…

二叉樹相關知識及求深度的代碼實現

文章目錄樹二叉樹滿二叉樹和完全二叉樹二叉樹的性質代碼實現求二叉樹的深度樹 樹是一種非線性的數據結構&#xff0c;它是由n個有限結點組成一個具有層次關系的集合。 樹的相關名詞&#xff1a; 根節點&#xff1a;沒有前驅結點的結點。父節點&#xff0c;子節點&#xff1a…

平衡樹相關知識及如何判斷一棵樹是否平衡

文章目錄概念代碼實現判斷一棵二叉樹是否為平衡樹概念 平衡樹(Balance Tree&#xff0c;BT) 指的是&#xff0c;任意節點的子樹的高度差都小于等于1。 常見的符合平衡樹的有&#xff1a; B樹&#xff08;多路平衡搜索樹&#xff09;AVL樹&#xff08;二叉平衡搜索樹&#xf…

大端小端存儲模式詳解及判斷方法

文章目錄大小端模式的概念兩種模式出現原因兩種模式的優劣大小端的應用情景判斷機器的字節序大小端模式的概念 當我們查看數據在內存中的存儲情況時&#xff0c;我們經常會發現一個很奇怪的現象&#xff0c;什么現象呢&#xff1f; int main() {int i 12;return 0; }數據在內…