Leetcode-050-pow(x,n)

Leecode-050-Pow(x, n)

思路:快速幂

题目描述

1
2
3
4
5
6
7
8
9
10
11
Input: 2.00000, 10
Output: 1024.00000


Input: 2.10000, 3
Output: 9.26100

// 负数的情况
Input: 2.00000, -2
Output: 0.25000
Explanation: 2-2 = 1/22 = 1/4 = 0.25

Solution1:快速幂+递归

  • 「快速幂算法」的本质是分治算法
  • 举个例子,如果我们要计算 x^64,我们可以按照:

    mark

    从 x 开始,每次直接把上一次的结果进行平方,计算 6 次就可以得到 x^64 的值

  • 再比如我们要计算 x^77,我们可以按照

mark

在这些步骤中,除了直接把上一次的结果进行平方,还要再结果进行平方后,额外乘一个x。

直接从左到右进行推导看上去很困难,因为在每一步中,我们不知道在将上一次的结果平方之后,还需不需要额外乘 x。但如果我们从右往左看,分治的思想就十分明显了:

算法总结如下:

mark

Solution2 : 快速幂+迭代

由于递归需要使用额外的栈空间,我们试着将递归转写为迭代。

我们还是以 x^77 作为例子

  • 贡献计算

mark

  • 二进制转换

mark

  • 因此我们借助整数的二进制拆分,就可以得到迭代计算的方法,一般地,如果整数 n 的二进制拆分为

mark

  • 总结:
  1. 从x开始不断平方,得到mark

  2. 如果n的第k个(从右往左,从 0 开始计数)二进制位是1,那么就将对应的贡献mark计入答案

Java

Solution : 快速幂+递归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution{
public double qucikMul(double x,long N){
// 如果指数是N=0
if (N == 0){
return 1.0;
}

// 分而治之
double y = qucikMul(x,N/2);
// N奇数偶数判断
return N % 2 == 0? y*y : y*y*x;
}

public double myPow(double x,int n){
// 把n转换成long类型
long N = n;
return N >= 0? qucikMul(x,N) : 1.0/qucikMul(x,-N);
}
}
  • 时间复杂度:O(logn) n 是递归的层数
  • 空间复杂度:O(logn) n 是递归的层数,递归自动使用栈空间

Solution : 快速幂+迭代

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution{
double quickMul(double x,long N){
double ans = 1.0;
// 贡献的初始值为 x
double x_contribute = x;

// 在对N进行二进制拆分的同时计算答案
while (N > 0){
if (N%2 == 1){
// 如果N二进制表示的最低位是1,要计入贡献
ans *= x_contribute;
}
// 将贡献不断的平方
x_contribute *= x_contribute;
// 舍弃N二进制表示的最低位,
// 这样我们每次只要判断最低位是不是1即可
N/=2;
}
return ans;
}

public double myPow(double x,int n){
long N = n;
return N>0? quickMul(x,N) : 1.0/quickMul(x,-N);
}
}
  • 时间复杂度:O(logn) 对数字n进行二进制拆分的时间复杂度
  • 空间复杂度:O(1)

Python

Solution :

1
2


打赏
  • 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!
  • © 2019-2022 Zhuuu
  • PV: UV:

请我喝杯咖啡吧~

支付宝
微信