算法思想:
-对于除了指数为零的情况外每种base ^ n,都有且仅有 base ^ n = base ^ (n / 2) * base ^ (n / 2) 或 base ^ n = base ^ (n / 2) * base ^ (n / 2) * base ^ 1 两种情况,因此可以得出以下递归/非递归算法
代码实现:
C++代码实现:
递归实现:
int getrow(int base,int n){ // base 为底数,n 为指数
if(n == 0){ // 递归出口:当 指数 等于0时,无论底数为何,结果值必为1
return 1;
}
int temp = getrow(base,n >> 1); // 递归,将 base^n 分解为 base ^ (n / 2) * base ^ (n / 2)
temp *= temp; // 将两份 base ^ (n / 2) 组合成 base ^ n
if((n & 1) != 0){ // 奇数二进制的末尾必为 1,而偶数二进制末尾必为 0;可以此来判断数奇偶
// 括号内逻辑表达式等价于 n % 2 != 0
temp *= base; // 因为当指数为奇数时,无法完全拆成等价的两份 base ^ (n / 2),因此组合后的值必为 base ^ (n - 1)
// 故而需要再给其乘以一个base,使其成为完整的 base ^ n
}
return temp; // 返回当前递归值
}
非递归实现:
int getrow(int base,int n){
// 非递归快速幂主要采用栈来代替原本的递归形式,这样可以有效减少空间开销
int ans = 1;
int *stark = new(int [n / 2 + 1]); // 为栈申请空间
int top = -1;
stark[++ top] = n;
while(n != 0){ // 循环将每一次分解后的指数放入栈中
stark[++ top] = n >> 1;
n >>= 1;
}
stark[++ top] = 0;
while(top > -1){
int temp = stark[top];
top -= 1;
if(temp == 0){
continue;
}
ans *= ans; // base ^ n = base ^ (n / 2) * base ^ (n / 2)
if((temp & 1) != 0){
ans *= base; // 如果 n 为奇数,则再在 base ^ (n - 1) 的基础上乘以一个 base
}
}
return ans;
}
Golang代码实现:
递归实现:
func getrow(base int,n int)(row int){
if n == 0{
row = 1
return
}
temp := getrow(base,n >> 1)
temp *= temp
if (n & 1) != 0{
temp *= base
}
row = temp
return
}
非递归实现:
func getrow(base int,n int)(row int){
row = 1
var stark = make([]int,0)
stark = append(stark,n)
for n != 0{
stark = append(stark,n >> 1)
n >>= 1
}
stark = append(stark,0)
for len(stark) > 0{
temp := stark[len(stark) - 1]
stark = stark[:len(stark) - 1]
if temp == 0{
continue
}
row *= row
if (temp & 1) != 0{
row *= base
}
}
return
}