快速幂算法 Pow(x,n)函数的实现
- 前言
如果要实现x的整数n次幂(xn),那么可以采用不同的策略,最直观和简单的算法就是利用递归或迭代把n个x连续相乘起来,从而获得幂乘结果。显而易见,此算法至少需要O(n)次运算,n比较大的情况下,则运算效率较低,且占用储存空间开销大。
鉴于此,算法中需要引入快速幂的计算模式,先看一个具体的例子,给定n=10的情况下,进行推理计算过程,
1->x->x2->x5->x10
经过仔细观察可发现,如果n次幂为奇数,x=y*y*x, 如果n次幂为偶数,那么x=y*y, 算式中y理解为当前n的前值。
- 递归计算
快幂的本质是分治,每次对指数的数值减半,从而最终求得结果。再举一个例子,鉴定要计算x77, 利用二分的分治思想,过程可以分解为:
- 代码实现
代码实现过程中值得学习的一点是,充分利用递归的返回结果进行计算,对递归的进行变量保存,然后再对这个变量进行处理,基本思路是先递归给出结果,然后再利用结果进行相关的计算,最后求出所需要的值。
/**
* @file quick_power.c
* @author your name (you@domain.com)
* @brief
* @version 0.1
* @date 2023-05-14
*
* @copyright Copyright (c) 2023
*
*/
#ifndef QUICK_POWER_C
#define QUICK_POWER_C
#include "quick_power.h"
double quick_power(double x, int n)
{
long N;
N=n;
return (N >= 0 ? quick_power_aux(x, N) : 1.0 / quick_power_aux(x, -N));
}
double quick_power_aux(double x, long n)
{
//Apply the tail processing mode
double y;
if(n==0)
{
return 1.0;
}
else
{
y=quick_power_aux(x,n/2);
return (n%2==0 ? y*y:y*y*x);
}
}
#endif
- 非递归的计算
- 非递归的代码实现
对于非递归的过程,主要是对幂指数进行位运算操作处理,通过位运算操作,最终求得所需结果。
/**
* @file quick_power.c
* @author your name (you@domain.com)
* @brief
* @version 0.1
* @date 2023-05-14
*
* @copyright Copyright (c) 2023
*
*/
#ifndef QUICK_POWER_C
#define QUICK_POWER_C
#include "quick_power.h"
double quick_power(double x, int n)
{
long N;
N=n;
return (N >= 0 ? quick_power_aux(x, N) : 1.0 / quick_power_aux(x, -N));
}
double quick_power_aux(double x, long n)
{
double res=1.0;
double base=x;
while(n>0)
{
if(n&1==1)
{
res=res*base;
}
base*=base; //base will get powered
n>>=1;
}
return res;
}
#endif
- 小结
通过对快幂算法学习,深入理解了对递归返回值的在处理方法,某种意义上,可以理解为“后序”处理的过程。
参考资料:
50. Pow(x, n) - 力扣(Leetcode)