力扣50号算法题Pow(x, n)。快速幂的递归与位运算实现及扩展题372. 超级次方

二分快速幂算法精讲:从原理到实战,攻克力扣50/372/1808题 幂运算是算法与编程中的基础操作,其核心在于高效计算a的b次方。传统循环乘法的时间复杂度为O(n),当指数b极大时性能堪忧。基于分治思想与二进制分解原理的快速幂算法,能将复杂度优化至O(log n),通过将指数不断二分或按二进制位处理,大幅减少乘法次数。这一优化在需要处理大数幂运算或模幂运算的场景中极具技术价值,例如计算哈希、加密解密、组合数学以及解决各类数学建模问题。本文以力扣经典题目为应用场景,深入解析快速幂的递归与迭代实现,并探讨其在处理指数为负数、大数数组表示及复杂数学推导中的实际应用,帮助读者掌握这 阅读详情

问题:力扣50. Pow(x, n)

解法一: 直接暴力for循环:

  • 就是通过for 循环 O(n) 时间复杂度,不断的进行累加, 会出现超时。

    // 暴力破解,O(n) 迭代
    func myPow(x float64, n int) float64 {
        // 如果指数小于 0,那么将底数变为对应的
        if n < 0 {
            x = 1 / x
            n = -n
        }
        var rst float64 = 1 
        for ;n > 0; n-- {
            rst *= x
        }
        return rst 
    }
    

解法二:递归实现快速幂:

  • 先来分析一波: 上面的暴力破解, O(n) 的时间复杂度,就是每次都是乘x, 那么可以将问题进行拆解:

  • 例如:

    • 3 ^ 16 == 3 ^ 8 * 3 ^ 8
    • 3 ^ 8 == 3 ^ 4 * 3 ^ 4
    • 3 ^ 4 == 3 ^ 2 * 3 ^ 2
    • 3 ^ 2 == 3 * 3
    • 类似 二分查找一样的,每次将问题范围缩小一半。那么时间复杂度就是 O(log n), n 表示指数, 上面的 16。
    • 我们使用递归实现这一过程,很像归并排序! 再递的时候,不断缩小范围,再归的过程,再去计算两两乘积,最后得到最终结果。
    func quickPow(x float64, n int) float64 {
        // 递归终止条件
        if n == 0 {
            return 1.0
        }
        // 分解 
        mid := n / 2
        // 递的过程,不断的缩小范围 16 - 8 - 4 - 2 - 1
        y := quickPow(x, mid)
        // 归的过程,就是 不断乘积
        return y * y
    }
    
  • 还需要考虑一个关键点是: 当前的值可能是 奇数, 例如

    • 3 ^ 19 == 3 ^ 9 * 3 ^ 9 * 3
    • 所以,上面的 y * y 应该进行判断, 如果是 偶数,就 y * y,如果是奇数,就需要 y * y * x 才是正确的!
  • 上最终代码:

    // 暴力破解,O(n) 迭代
    func myPow(x float64, n int) float64 {
        // 1. 快速幂计算
        var quickPow func(float64, int) float64
        quickPow = func(x float64, n int) float64 {
            // 两个递归终止条件, 必须有下面一个 0 的判断 才能对
            // if n == 1 {
            //     return x 
            // }
            if n == 0 {
                return 1.0
            }
            // 分解 
            mid := n / 2
            // 递归
            y := quickPow(x, mid)
            // 可能是 奇数,3 ^ 19 == 3 ^ 9 * 3 ^ 9 * 3
            if n % 2 == 0 {
                return y * y
            } else {
                return y * y * x
            }
        }
        
        // 2. 如果指数小于 0,那么将底数变为对应的
        if n < 0 {
            x = 1 / x
            n = -n
        }
        
        // 3. 调用快速幂进行计算
        return quickPow(x, n)
    }
    

解法三: 位运算优化实现

  • x ^ 15 , 对于指数进行分解, 拆为2进制表示

    • 15 = 1111 。 那么 要知道 二进制从低到高 每位的表示为 1, 2, 4, 8.
    • 将当前的结果就 转换为了: x ^ (2^1) * x ^ (2^2) * x ^ (2^4) * x ^ (2^8)
    • 并且每一位上是有 规律的。 将上面的四个部分表示为 y1 * y2 * y3 * y4
      • 那么 ,根据指数 1 ,2 ,4, 8的关系。两数相乘等于指数相加
      • y2 = y1 * y1
      • y3 = y2 * y2
      • y4 = y3 * y3
    • 那么我们将指数,化为 2进制形式, 按照上面的规律 求得 y1 到 y4,再将他们累乘,就是最后的结果了。
    • 下面计算 x ^ 15 次方,可以写成这样:
    // 定义结果
    rst := 1.0
    // 15 = 1111
    // 循环, 取 n代表指数, 取它的每一位。利用右移运算符。
    // 当n 还大于0,就右移一位。等于取每一位
    for n != 0 {
    	// 第一位 为 1, y1 = x ^ 1 , 等于 x 
        rst *= x
        // 到了下一位 因为 1 2 4 8, 所以下一位,等于当前 y1 * y1 == x * x
        x *= x
        // 右移一位
        n >>= 1 
    }
    // 循环这个过程, y2 = y1 * y1 。。。
    // 然后 rst 累乘每一步的结果。 每一步的结果,又是上一步 相乘。 
    // x^2 * x^2 == x ^ (2 + 2) == x ^ 4 , 对应2进制每一位 1 2 4 8
    return rst 
    
  • 由上面的结果,还有一定的 bug!, 因为我们选择的是 x ^ 15

    • 15 = 二进制 1111 , 所以每一步二进制计算的 结果 “y” 累乘起来就是最终结果。
    • 但是 如果是 x^ 9 呢? 9 == 1001(二进制). 也就是说
    • x ^ 9 == (x ^ 8) * (x ^ 0) * (x ^ 0) * (x ^ 1)
    • x ^ 0 == 1, 也就是说 ,x ^ 9 == (x ^ 8) * 1 * 1 * (x ^ 1)
    • 所以,我们要进行判断, 当,当前二进制位为 0的时候,rst 结果不能 乘以 当前的 y, 而应该跳过。因为 乘 1 等于自身。但是 y2 == y1 * y1 不变。 即使当前的 二进制位为 0, rst 不累乘,但是还要计算下一次的 y
  • 最终的代码:

    • 因为 是在 int32 范围内,所以最多取 32位,时间复杂度是 O(32),空间复杂度是O(1)。
    // 位运算最优解,  快速幂 + 迭代
    // 因为计算结果在 int32 范围内, 所以 
    // 空间复杂度为 O(1), 时间复杂度为 O(32)
    func myPow(x float64, n int) float64 {
        // 1. 如果指数小于 0,那么将底数变为对应的
        if n < 0 {
            x = 1 / x
            n = -n
        }
        rst := 1.0
        for n != 0 {
        	// 当前二进制位等于 1才累加到结果集
            if n & 1 == 1 {
                rst *= x
            }
            // 下一轮的 y 值,等于当前 y 值相乘
            x *= x
            n >>= 1 
        }
        return rst 
    }
    

问题 :力扣 372. 超级次方

  • 有了上面快速幂的基础, 我们可以看下面这道题,可以使用快速幂解答。
    在这里插入图片描述

  • 这道题 求得就是 a^b 对 1337 取模。 先需要求得 a 的 b次方,再进行 1337 取模。且 b 是个很大的数,超过32位。

    // 按照理论: https://leetcode-cn.com/problems/super-pow/solution/gong-shui-san-xie-di-gui-kuai-su-mi-ying-yx1j/ 
    // 这个大佬的讲解,只要将最后的数字转换为 
    const mod = 1337
    
    func pow(x, n int) int {
        res := 1
        for ; n > 0; n /= 2 {
            if n&1 > 0 {
                res = res * x % mod
            }
            x = x * x % mod
        }
        return res
    }
    
    func superPow(a int, b []int) int {
        ans := 1
        for i := len(b)-1; i >= 0; i-- {
            ans = ans * pow(a, b[i]) % mod
            a = pow(a, 10)
        }
        return ans
    }
    
    
同余定理和快速幂模运算:从‘末两位数’题到LeetCode高频算法题的实战打通 本文深入探讨同余定理和快速幂模运算在算法竞赛和LeetCode高频题中的应用。从基础数学原理出发,详细解析递归与迭代实现的快速幂算法,并结合LeetCode实战案例(如超级次方、Pow(x,n)等),展示如何高效解决幂取模问题。文章还提供工程优化技巧和面试应对策略,帮助开发者掌握这一核心算法技能。 阅读详情

相关推荐

国科大 雁栖湖校区 研一上 课程避坑与生存指南

本文为国科大雁栖湖校区研一新生提供全面的课程避坑与生存指南,涵盖选课策略、核心课程学习技巧、校园生活攻略及心态管理。重点解析算法设计与分析、人工智能原理等硬核课程的学习方法,并分享食堂、住宿、自习室等实用生存技巧,帮助新生高效适应研究生生活。

weixin_29304985的博客 299

【力扣】231. 2 的幂【多方法超详解】

力扣,求2的幂的思路解答

pakerder的博客 2851

STorM BGC V1.31硬件+SimpleBGC固件:从零搭建三轴云台开发环境(Keil+JLink避坑指南)

本文详细介绍了如何从零搭建STorM BGC V1.31硬件+SimpleBGC固件的三轴云台开发环境,涵盖硬件连接、Keil+JLink开发工具配置、固件编译与烧录等关键步骤,并提供了常见问题的解决方案和调试技巧,帮助开发者快速上手三轴云台开发。

weixin_28693683的博客 380

力扣刷题快速乘算法

快速乘算法

xianzhetime的博客 220

疑难问题(二)——PyTorch 2.3.0 ‘import torch‘ 错误排查:深入解析‘shm.dll‘加载失败与系统路径修复

本文深入解析了在Windows系统上安装PyTorch 2.3.0后,执行'import torch'时遇到的'shm.dll'加载失败错误(OSError)。该问题通常源于系统DLL搜索路径缺失,导致无法找到关键的共享内存通信组件或其依赖项。文章提供了核心解决方案:通过手动修改PyTorch的`__init__.py`文件,将用户基目录下的Library\bin路径添加到DLL搜索列表中,从而从根本上修复此导入错误,并给出了详细的修改步骤和验证方法。

weixin_29056865的博客 305

【软考】系统集成项目管理工程师(一)信息化知识

软考中级——系统集成项目管理工程师备考干货第一章:信息化知识。

商务合作 | 共同学习 | 携手共进 9万+

【leetcode 力扣刷题】数学题之计算次幂//次方:快速幂

massive_jiang的博客 1036

【漏洞复现】用友U9 UMWebService.asmx 任意文件读取漏洞

用友U9存在任意文件读取漏洞,未授权的攻击者可以通过该漏洞读取服务器任意文件,造成敏感信息泄露。

qq_67810151的博客 620

力扣LeetCode经典算法 数值的整数次方

实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn)。不得使用库函数,同时不需要考虑大数问题。

胡乱写点什么 379

Python爬虫:实时交通流量数据爬取与路况分析

随着城市化进程的不断推进,交通流量的管理与预测已成为智能交通系统的重要研究方向。交通流量数据不仅为城市交通管理提供了科学依据,还为驾驶员提供了实时路况信息,帮助其做出更加合理的出行决策。通过爬虫技术,我们可以实时获取城市的交通流量数据,从而分析路况,优化交通管理。在这篇博客中,我们将介绍如何使用Python编写一个爬虫来爬取实时交通流量数据,分析道路的交通状况。我们将使用最新的技术工具来构建爬虫,包括。

2201_76125261的博客 1267

YOLOv13涨点改进 | 独家创新、Neck特征融合改进篇 | TGRS 2024 | 引入 EFC增强跨层特征相关创新点,含MSEF(多尺度有效融合模块)二次创新模块,助力遥感目标检测涨点

本文提出EFC(增强跨层特征相关)模块改进YOLOv13模型,显著提升小目标检测性能。EFC通过分组特征聚焦(GFF)和多层特征重建(MFR)增强特征融合效率,在小目标检测任务中平均精度(mAP)提升1.7%,同时减少模型计算量。实验验证EFC在VisDrone等数据集上的有效性,改进后的模型能更好地保留小目标细节信息。还提出二次创新模块MSEF,集成通道和位置注意力机制,进一步优化特征表达。文章详细介绍了模块配置方法和yaml文件修改步骤,为小目标检测任务提供了实用的改进方案。

Ai缝合怪、助力小伙伴高效发论文 325

【算法】LeetCode372. 超级次方(每日一题)Java

利用分治法将很大的数拆分成多份,分别区余数。 例如: 2^433852可以分成 2^(43385*10+2) ==> (2^43385)^10 ==> (2^43385)^10*2^2 public class LC0372 { int mol=1337; public int superPow(int a, int[] b) { return dfs(a,b,b.length-1); } int dfs(int a,int[]...

m0_57099044的博客 313

Python爬虫实战:基于最新技术栈的晋江文学城小说爬取

本文将详细介绍如何使用Python最新技术栈构建一个高效的晋江文学城小说爬虫。我们将从爬虫基础知识讲起,逐步深入到反爬机制应对、分布式爬虫设计以及数据存储优化等高级话题。文章包含完整的代码实现,使用aiohttp+asyncio实现异步爬取,Playwright处理动态渲染,并结合Redis实现分布式任务队列。本文旨在为读者提供一个全面的现代Python爬虫开发指南。网络爬虫(Web Crawler)是一种自动抓取互联网信息的程序,广泛应用于搜索引擎、数据分析和内容聚合等领域。

2201_76125261的博客 869

LeetCode 50. Pow(x, n)(二分查找)

文章目录1. 题目2. 二分查找2.1 递归2.2 循环 1. 题目 实现 pow(x, n) ,即计算 x 的 n 次幂函数。 示例 输入: 2.00000, 10 输出: 1024.00000 示例 输入: 2.00000, -2 输出: 0.25000 解释: 2-2 = 1/22 = 1/4 = 0.25 说明: -100.0 < x < 100.0 n 是 32 位有符号整数...

Michael是个半路程序员 1452

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

【LeetCode】372. Super Pow 超级次方

你的任务是计算 ab 对 1337 取模,a 是一个正整数,b 是一个非常大的正整数且会以数组形式给出。 负雪明烛,leetcode,力扣,算法,372,超级次方

负雪明烛 2126

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

力扣:快速幂问题总结(50、372)

一、计算ana^nan的3种方法 1.累乘法(不推荐) double res = 1.0; while(n-- > 0) { res *= a; } 时间复杂度:O(n); 乘法运算本身就耗时,所以这种方式不适合用于刷力扣题。 2.快速幂(二进制取幂) (1)思路 ①等价变换:513=5(1101)2=51⋅20+0⋅21+1⋅22+1⋅23=51⋅20⋅50⋅21⋅51⋅22⋅51⋅235^{13} = 5^{(1101)_2} = 5^{1·2^0+0·2^1+1·2^2+1·2^3}=5

南七行者的博客 801

C++/python描述 LeetCode 50. Pow(x, n)

C++/python描述 LeetCode 50. Pow(x, n)   大家好,我叫亓官劼(qí guān jié ),在优快云中记录学习的点滴历程,时光荏苒,未来可期,加油~博主目前仅在优快云中写博客,唯一博客更新的地址为:亓官劼的博客 ,同时正在尝试在B站中做一些内容分享,B站主页为: 亓官劼的B站主页 由于学习工作的需要,算法刷题将会逐渐由C++向Python3过度,正在过度中,如实现的不太优美,请见谅。 本文原创为亓官劼,请大家支持原创,部分平台一直在恶意盗取博主的文章!!!

一起加油 931

二分快速幂模板//分治:50.pow(x,n) 372.超级次方 1808.好因子的最大数目

学C++的最舒服的一件是:存在大量的,完善的标准函数模板。 从C继承过来的一堆头文件,加上cpp后来发展的标准化模块(STL),由此可以方便地调用各个函数(模板),实现丰富的操作。 所以...... 经历了多次提交实验,发现 ...

01解题者~博客 839

leetcode系列题七----快速幂

leetcode系列题七----快速幂

qq_37395293的博客 6187

《算法零基础》第15讲:二分快速幂 前两题题解

二分快速幂

Sauron7i的博客 221

别再傻傻循环了!用Python实现快速幂,LeetCode刷题效率翻倍(附模运算技巧)

本文详细介绍了快速幂算法在LeetCode刷题中的应用,通过递归和迭代两种实现方式,显著提升计算效率。文章还涵盖了模运算技巧和矩阵快速幂等扩展应用,帮助开发者高效解决大数幂计算问题,特别适合算法竞赛和日常编程挑战。

weixin_30296405的博客 355

[Leetcode 每日精选] 50. Pow(x, n)

题目难度: 中等 原题链接 扩展思考: 372-超级次方, 感兴趣的同学可以尝试下这道题, 看看能不能扩展一下思路, 举一反三? 题目描述 实现 pow(x, n) ,即计算 x 的 n 次幂函数。 -100.0 < x < 100.0 n 是 32 位有符号整数,其数值范围是 [−2^31, 2^31 − 1] 。 题目样例 示例 1 输入 2.00000, 10 输出 1024.00000 示例 2 输入 2.10000, 3 输出 9.26100 示例 3 输入 2.000.

随便发挥的博客 219

leetcode 快速幂

快速幂算法 快速幂就是快速算底数的n次幂,其时间复杂度为 O(log₂N) 例如: 求710求 7^{10}求710 710=75+5=75∗75,而75=72∗72∗77^{10} = 7^{5+5} = 7^{5}*7^{5},而7^{5}=7^{2}*7^{2}*7710=75+5=75∗75,而75=72∗72∗7 code leetcode 50 Pow(x,n) 实现x的...

weixin_41964962的博客 603

从‘末两位数’问题出发,带你玩转递归、迭代、递推三种代码思维(附LeetCode同类题推荐)

本文从‘末两位数’问题出发,深入探讨了递归、迭代和递推三种编程范式的实现与优化。通过对比分析,揭示了快速幂算法在幂取模问题中的高效应用,并结合同余定理和LeetCode实战案例,帮助读者掌握算法思维的核心技巧与适用场景。

weixin_30325487的博客 266

快速幂算法相关题目(Leetcode题解-Python语言)

50. Pow(x, n) 快速幂算法的目的,就是快速计算 x 的 n 次方。基本思路是把 n 视作二进制数,则 n 可以被分解为多个 2 的幂次方之和,如 12 对应 1100 等于 0∗20+0∗21+1∗22+1∗230*{2^0} + 0*{2^1} + 1*{2^2} + 1*{2^3}0∗20+0∗21+1∗22+1∗23,即二进制数中每一位的0或1对应的正是系数。因此,x12=x0∗20+x0∗21+x1∗22+x1∗23{x^{12}} = {x^{0*{2^0}}} + {x^{0*{2^

自动化研究生在读,此博客记录了我的学习与刷题经验,欢迎大家阅读交流 763

leetcode-快速幂/平方/相加/相除

69. x 的平方根 https://leetcode-cn.com/problems/sqrtx/

MaYingColdPlay的博客 328
上一篇: 红黑树的应用与力扣456号算法题132模式详解,go语言解题
下一篇: (4)go web开发之 JWT-Token认证机制Access Token与Refresh Token及 jwt-go 库介绍及在项目中使用
我是py呀
博客等级 码龄8年 205粉丝 130原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值