首页 > 其他分享 >快速幂

快速幂

时间:2023-12-24 16:32:25浏览次数:23  
标签:return int double result pow 次方 快速

快速幂(Exponentiation by squaring)或者叫平方求幂,是一种求幂函数算法。

它可以以O(logN)的时间复杂度求任意乘方。

引入

如何求8的6次方

常规算法:

private double pow(double x, int y) {
    double result = 1;
    for (int i = 0; i < y; i++) {
        result *= x;
    }
    return result;
}

实际上,这样的暴力相乘并不高效。

再回想数学公式: $$ a ^ n * a ^ n = a ^ {2n} \ a ^ n * a ^ m = a ^ {n + m} $$ 那我们实际上可以理一下我们的思路,我们要计算 6 次方。

那么实际上可以将式子简化为: $$ 8 ^ 6 = 8 ^ 3 * 8 ^ 3 ;;;① \ 8 ^ 3 = 8 ^ 2 * 8 ^ 1;;;②\ 8 ^ 2 = 8 ^ 1 * 8 ^ 1;;;③ $$ 根据上述理论,可以写出如下方程式: $$ a ^ n = \left{\begin{matrix} a ^ {n - 1},;;;;;;;; n是奇数\ a ^ \frac{n}{2} * a ^ \frac{n}{2},;;;; n是偶数 \ 1,;;;;;;;;;;;n为0 \end{matrix}\right. $$ 翻译为代码则为:

private double pow(double x, int y) {
        if (y == 0) {
            return 1;
        } else if (y % 2 == 1) {
           return pow(x, y - 1) * x; 
        } else {
            double temp = pow(x, y / 1);
            return temp * temp;
        }
    }

其中,利用到了 二分查找 的思想。

递归虽然简洁,但会产生额外的空间开销。将递归改写为循环,来避免对栈空间的大量占用,也就是非递归快速幂

非递归快速幂

从另一个视角引入快速幂:

如果你的数学基础牢固,那你应该可以很快想到:

任何自然数都可以转化为 2的n次方相乘 这是由二进制表达所决定的。

例如: $$ 2023 = (0111; 1110; 0111)_{2} = 2^0+2^1+2^2+2^5+2^6+2^7+2^8+2^9+2^{10} $$ 二进制上从右往左第n位,分别代表2 的 n - 1次方,而所有的数都可以用二进制表示,所以我们可以根据二进制来优化幂的计算。

也就是说,所有的幂计算都可以看作是底数的2的n次方幂相乘

例如: $$ 3^{999} = 3^{512}+3^{256}+3^{128}+3^{64}+3^{32}+3^{4}+3^{2}+3^{1} $$ 其中 512、256、128、64、32、4、2和1都是 2 的 n 次方。

将以上理论转化为代码可得:

double pow(double x, int y)
    {
        double result = 1;
        while (y != 0)
        {
            if ((y & 1) == 1) {
                result *= x;
            }
            y >>= 1;      
            x *= x;
        }
        return result;
    }

在每次循环,x 都会成为 x 的平方。

第一次循环是 x 的 2 次方,第二次循环是 x 的 4 次方,以此类推。最终通过上述理论快速计算幂,节省堆栈开销。

标签:return,int,double,result,pow,次方,快速
From: https://blog.51cto.com/ErickRen/8956103

相关文章

  • MyBatisPlus简介及快速搭建
    一、简介MyBatisPlus(简称MP)是一个MyBatis的增强工具,在MyBatis的基础上只做增强,不做改变,为简化开发,提高效率而生。特性及官网链接(简称苞米豆):可在IDEA中安装以下插件:MybatisX:支持跳转,自动补全生成SQL;dynamic-datasource:基于SpringBoot的多数据源组件,功能强悍,支持Seat......
  • 详解十大经典排序算法(六):快速排序(QuickSort)
    算法原理分区(Partition):选择一个基准元素,将数组分为两个子数组,小于基准的放在左边,大于基2准的放在右边。递归排序:对左右两个子数组分别进行快速排序。合并:不需要实际的合并操作,因为在分解和递归排序阶段已经完成了排序。算法描述快速排序是一种基于分治思想的高效排序算法,由英国......
  • 算法学习笔记五一快速排序
    目录什么是快速排序算法思想示例代码什么是快速排序快速排序(Quicksort)是一种常用的排序算法,它的基本思想是通过分治的策略将一个大问题划分为多个小问题来解决。它的平均时间复杂度为O(nlogn),最坏情况(有序情况)为O(n^2)。是一种高效的排序算法。算法思想选择一个基准元素(pivot......
  • 一款基于.NET Core的快速开发框架、支持多种前端UI、内置代码生成器
    前言经常看到有小伙伴在技术群里问有没有什么好用且快速的开发框架推荐的,今天就给大家分享一款基于MITLicense协议开源、免费的.NETCore快速开发框架、支持多种前端UI、内置代码生成器、一款高效开发的利器:WalkingTec.Mvvm框架(简称WTM)。官方项目介绍WalkingTec.Mvvm框架(简称W......
  • golang快速入门:并发编程(一)
    进程、线程和协程进程:是操作系统中的一个执行实体,它拥有独立的内存空间和系统资源。每个进程都是独立运行的,它们之间相互隔离,通过进程间通信(IPC)来进行数据交换。每个进程都有自己的地址空间、堆栈和文件描述符等。进程之间的切换开销较大,因为需要保存和恢复整个进程的状态。线程:是......
  • 快速数论变换 | NTT 初学
    快速数论变换|NTT初学前置FFT原根阶:称满足同余方程\(a^x\equiv1\modm\)的最小正整数解\(x\)为\(a\)的模\(m\)的阶,记为\(Ord_ma\)。观察到本质就是最短循环节,同时该同余方程类似于欧拉定理:\[a^{\varphi(m)}\equiv1\modm,a\botm\]那么显然两者的关系是......
  • 【快速应用开发】看看RedwoodJS
    自我介绍做一个简单介绍,酒架年近48,有20多年IT工作经历,目前在一家500强做企业架构.因为工作需要,另外也因为兴趣涉猎比较广,为了自己学习建立了三个博客,分别是【全球IT瞭望】,【架构师酒馆】和【开发者开聊】,有更多的内容分享,谢谢大家收藏。企业架构师需要比较广泛的知识面,了解一个企业......
  • 运用ETL快速拉取吉客云平台订单信息
    吉客云介绍吉客云是一家中国的云计算服务提供商。它提供了包括云服务器、云数据库、云存储、云网络等各种云计算产品和解决方案,帮助企业和个人搭建高效、可靠、安全的云计算环境。吉客云特点和优势:大规模分布式架构:吉客云基于自主研发的分布式技术,构建了覆盖全国各地的大规模......
  • 快速窗口定位功能
    HHDBCS及HHDESK都设置有快速窗口定位功能,支持用户快速定位到已经打开的窗口。点击软件右侧的小扳手,弹出对话框;可进行搜索;......
  • Zookeeper-快速入门、服务搭建、集群搭建教程
    官网:https://zookeeper.apache.org/zookeeper常用用途:集群管理,zookeeper作为注册中心,管理服务提供方的ip地址端口号url信息,并在服务消费方请求需要时发送给服务消费方。配置中心(不过一般用阿波罗apollo或者阿里的Nacos来做)多个app中的配置是从zookeeper中拉取配置,而不是一个......