小编典典

让我们从一些数学事实开始:

对于正n,aⁿ=a⨯a⨯…⨯an次

对于负数n,aⁿ=⅟a⁻ⁿ=⅟(a⨯a⨯…⨯a)。这意味着 a 不能为零。

对于n = 0,即使 a 为零或负,aⁿ= 1 。

因此,让我们从n个正数开始,然后从那里开始。

因为我们希望我们的解决方案是递归的,所以我们必须找到一种方法来基于较小的n定义aⁿ,然后从那里开始。人们通常认为递归的方法是尝试找到n-1的解,然后从那里开始工作。

实际上,由于a since =a⨯(aⁿ⁻¹)在数学上是正确的,因此幼稚的方法将与您创建的方法非常相似:

public static int pow( int a, int n) {

if ( n == 0 ) {

return 1;

}

return ( a * pow(a,n-1));

}

但是,其复杂度为O(n)。为什么?因为对于n = 0,它不做任何乘法。对于n = 1,它执行一次乘法。对于n =

2,它调用pow(a,1),我们知道它是一个乘法,并将其相乘一次,所以我们有两个乘法。在每个递归步骤中都有一个乘法,有n个步骤。所以是O(n)。

为了使这个O(log n),我们需要将每个步骤应用于n 的 一部分 ,而不仅仅是n-1。在这里,有一个数学的事实,可以帮助我们:一个N 1 + N

2 = A 区N1 ⨯a 氮气。

这意味着我们可以将aⁿ计算为n / 2⨯an / 2。

但是,如果n为奇数会怎样?像a⁹将是一个4.5 ⨯a

4.5。但是我们在这里谈论整数幂。处理分数是完全不同的事情。幸运的是,我们可以将其表述为a⨯a⁴⨯a⁴。

因此,对于偶数,使用n / 2⨯an / 2;对于奇数,使用a⨯a n / 2⨯an / 2(整数除法,得到9/2 = 4)。

public static int pow( int a, int n) {

if ( n == 0 ) {

return 1;

}

if ( n % 2 == 1 ) {

// Odd n

return a * pow( a, n/2 ) * pow(a, n/2 );

} else {

// Even n

return pow( a, n/2 ) * pow( a, n/2 );

}

}

这实际上为我们提供了正确的结果(对于n为正数)。但实际上,这里的复杂度还是O(n)而不是O(log

n)。为什么?因为我们要计算两次幂。这意味着我们实际上在下一级别将其称为4次,在下一级别将其称为8次,依此类推。递归步骤的数量是指数的,因此可以通过我们将n除以2来实现的节省被抵消。

但实际上,只需要进行一些小的更正:

public static int pow( int a, int n) {

if ( n == 0 ) {

return 1;

}

int powerOfHalfN = pow( a, n/2 );

if ( n % 2 == 1 ) {

// Odd n

return a * powerOfHalfN * powerOfHalfN;

} else {

// Even n

return powerOfHalfN * powerOfHalfN;

}

}

在此版本中,我们仅调用一次递归。因此,我们很快就从64的幂中获得了32、16、8、4、2、1,然后完成了。每一步只有一个或两个乘法,只有六个步。这是O(log

n)。

所有这些的结论是:

为了获得O(log n),我们需要递归,该递归在每个步骤上只占n的一部分,而不只是n-1或n-任何东西。

但是,这只是故事的一部分。我们需要注意不要多次调用递归,因为在一个步骤中使用多个递归调用会创建指数复杂度,而使用n的分数会抵消该复杂度。

最后,我们准备好处理负数。我们只需要得到倒数⅟a⁻ⁿ。有两件事要注意:

不允许被零除。也就是说,如果a == 0,则不应执行计算。在Java中,在这种情况下会引发异常。最合适的现成异常是IllegalArgumentException。这是RuntimeException,因此您无需在方法中添加throws子句。main读参数时,如果在方法中捕获了它或阻止了这种情况的发生,那将是很好的。

您无法再返回整数(实际上,我们应该使用long,因为使用会以很低的幂遇到整数溢出int)-因为结果可能是分数。

因此,我们定义该方法,使其返回double。这意味着我们还必须修复的类型powerOfHalfN。结果如下:

public static double pow(int a, int n) {

if (n == 0) {

return 1.0;

}

if (n < 0) {

// Negative power.

if (a == 0) {

throw new IllegalArgumentException(

"It's impossible to raise 0 to the power of a negative number");

}

return 1 / pow(a, -n);

} else {

// Positive power

double powerOfHalfN = pow(a, n / 2);

if (n % 2 == 1) {

// Odd n

return a * powerOfHalfN * powerOfHalfN;

} else {

// Even n

return powerOfHalfN * powerOfHalfN;

}

}

}

请注意,处理负数n的部分仅在递归的顶层使用。一旦我们pow()递归调用,它总是带有正数,并且直到它达到0为止,符号都不会改变。

那应该是您运动的适当解决方案。但是,个人而言,我不喜欢if最后的内容,因此这里是另一个版本。你能告诉我为什么这样做吗?

public static double pow(int a, int n) {

if (n == 0) {

return 1.0;

}

if (n < 0) {

// Negative power.

if (a == 0) {

throw new IllegalArgumentException(

"It's impossible to raise 0 to the power of a negative number");

}

return 1 / pow(a, -n);

} else {

// Positive power

double powerOfHalfN = pow(a, n / 2);

double[] factor = { 1, a };

return factor[n % 2] * powerOfHalfN * powerOfHalfN;

}

}

2020-11-13

幂函数c语言递归算法,使用递归的幂函数相关推荐

  1. c语言上20级台阶递归法,c语言递归算法.pptx

    计算机语言与程序设计;第八章 递归算法;从前有座山,山上有座庙,庙里有一个老和尚和一个小和尚,老和尚正在给小和尚讲故事.讲的是什么故事呢?他说,从前--;Recursion- See "Re ...

  2. c语言递归求和函数,c语言递归算法怎么实现

    递归就是一个方法自己调用自己.在编程语言中,如果一个程序允许您在同一个函数中调用一个函数,那么它就被称为函数的递归调用. void recursion() { recursion(); /* 函数调用 ...

  3. 基于c语言的递归算法分析论文,浅谈C语言递归算法.docx

    浅谈C语言递归算法 浅析C语言递归算法王浏江盐城师范学院 信息工程学院 计算机161班 摘要:递归算法,结构清晰,代码简练,函数调用灵活方便,比较容易理解和阅读.因此,递归算法一般用于多个相似小问题组 ...

  4. c语言如何实现递归算法,c语言递归算法如何实现

    c语言递归算法如何实现 发布时间:2020-09-22 14:22:05 来源:亿速云 阅读:186 作者:小新 这篇文章将为大家详细讲解有关c语言递归算法如何实现,小编觉得挺实用的,因此分享给大家做 ...

  5. C语言程序设计递推递归n,软考程序员考点C语言程序设计之递归法

    下面希赛小编为大家整理的软考程序员考点C语言程序设计之递归法,希望能帮助学友们.具体内容如下: 递归法 递归法是设计和描述算法的一种有力的工具,由于它在复杂算法的描述中被经常采用,为此在进一步介绍其他 ...

  6. C语言递归算法十进制数转换为八进制(附完整源码)

    C语言递归算法十进制数转换为八进制 C语言递归算法十进制数转换为八进制完整源码 C语言递归算法十进制数转换为八进制完整源码 #include <stdio.h> int decimal_t ...

  7. C语言递归算法将十进制转换为二进制(附完整源码)

    C语言递归算法将十进制转换为二进制 C语言递归算法将十进制转换为二进制完整源码 C语言递归算法将十进制转换为二进制完整源码 #include <assert.h>/*** Decimal ...

  8. 【C语言】利用递归解决猴子吃桃问题

    [C语言]利用递归解决猴子吃桃问题 参考文章: (1)[C语言]利用递归解决猴子吃桃问题 (2)https://www.cnblogs.com/ieybl/p/6597937.html 备忘一下.

  9. C语言函数递归调用实验报告,C语言函数的递归和调用实例分析

    一.基本内容: C语言中的函数可以递归调用,即:可以直接(简单递归)或间接(间接递归)地自己调自己. 要点: 1.C语言函数可以递归调用. 2.可以通过直接或间接两种方式调用.目前只讨论直接递归调用. ...

  10. XDOJ 363 输出快速排序递归算法隐含递归树的后序遍历序列 AC

    像我这样的菜鸡也没有什么能输出的,好像我写题解也不算输出. 最近期末了,写数据结构实验的时候,这个题写了挺久的,搞出来记录一下. 输出快速排序递归算法隐含递归树的后序遍历序列 描述: 快速排序递归算法 ...

最新文章

  1. MinGW-notepad++开发c/c++程序
  2. spoolsv.exe占CPU100% 的解决方法
  3. 使mysql查询条件区分大小写 数据库搜索中大小写敏感性
  4. Delphi的类与继承
  5. Python教程:collections的deque()方法
  6. 字符串 CSV解析 表格 逗号分隔值 通讯录 电话簿 MD
  7. 【eclipse转idea的第一天】配置idea
  8. 在centos7上设置swap交换空间
  9. 转载杨绛《一百岁感言》
  10. sql设为简单模式sql_SQL模式演练
  11. 如何知道PostgreSQL数据库下每个数据库所对应的目录
  12. 大厂“降本增效”后招聘要求,这项目经验和技术能力...,绝了
  13. 很无聊但是又很重要的 计算机网络基础知识 ---“互联网协议“
  14. 产品读书《用户力:需求驱动的产品、运营与商业模式》
  15. OpenCV:旋转矩形(RotatedRect)
  16. CentOS系统编译部署nginx-http-flv-module模块搭建流媒体服务器
  17. [概率论]艾波寧捎信(poisson分布)
  18. 2023年计算机考研数学考一还是二?考研数学一二三区别
  19. win10蓝牙故障无法正常使用的有效解决方法
  20. c语言响铃编程,C语言C加加编程新手快速入门基础学习

热门文章

  1. 合取式/合取范式/主合取范式/重言式/矛盾式 基本概念
  2. Java拿到前一天的零点零分
  3. 创建维基百科,编辑维基百科的四个技巧
  4. 用自己的域名配置动态域名解析(DDNS) (二)
  5. CTF warmup
  6. oracle 索引详解 注:转自红黑联盟非原创
  7. iOS 多语言本地化 完美解决方案【自动+手动】
  8. win10检测不到第二个显示器怎么解决 win10外接显示器黑屏怎么办
  9. PyTorch学习(二):Transform
  10. 利用Python进行博客图片压缩