[leetcode]50. Pow(x, n)

  • 个人博客:https://javaniuniu.com/
  • 难度:中等
  • 本题涉及算法: 递归 折半计算 快速幂
  • 思路: 递归 折半计算 快速幂
  • 类似题型:

50. Pow(x, n)

实现 pow(x, n) ,即计算 x 的 n 次幂函数。

示例 1:

输入: 2.00000, 10
输出: 1024.00000

示例 2:

输入: 2.10000, 3
输出: 9.26100

示例 3:

输入: 2.00000, -2
输出: 0.25000
解释: 2-2 = 1/22 = 1/4 = 0.25

说明:

-100.0 < x < 100.0
n 是 32 位有符号整数,其数值范围是 [−231, 231 − 1] 。

方法一 暴力

解题思路 时间会超时
  • 先对 n 的正负做判断
  • 当 n 为正数 x n x^n xn
  • 当 n 为负数 ( 1 / x ) n (1/x)^n (1/x)n
java
class Solution {
    public double myPow(double x, int n) {
        double a = 1.0;
        if(n<0) {
            x = 1/x;
            n = -n;
        }
        for(int i = 0;i<n;i++) {
            a *=x;
        }
        return a;
    }
}

方法二 改良暴力

  • 通过折半计算,每次把 n 减半,降低空间复杂度
java
class Solution {
    public double myPow(double x, int n) {
        double a = 1.0;
        if(n<0) {
            x = 1/x;
            n = -n;
        }
        for(int i = n;i != 0;i /= 2) {
            if (i % 2 != 0)
                a *= x;
            x *=x;
        }
        return a;
    }
}
python
class Solution(object):
    def myPow(self, x, n):
        """
        :type x: float
        :type n: int
        :rtype: float
        """
        res = 1;
        if n == 0:
            return 1
        if n < 0:
            x = 1 / x
            n = -n
        while n:
            if n % 2 == 0:
                x *= x
                n /= 2
            else:
                res *=x
                n -= 1
        return res

方法三 递归

解题思路

主要是注意n的正负,这个题比较简单了,直接递归调用就行。

  • 如果 n 是负数,那么相当于求 (1/x)^(-n)
  • 如果 n 是正数 且 奇数,那么结果需要单独乘以 x
  • 如果 n 是正数 且 偶数,求 (x^2)^(n/2),一直递归下去即可。
  • 时间复杂度是 O ( 1 ) O(1) O(1),空间复杂度是 O ( 1 ) O(1) O(1)
  • 我认为这个代码是 O ( 1 ) O(1) O(1),因为n只有32位,循环次数是有上限的常数

代码

class Solution {
    public double myPow(double x, int n) {
        if(n==0)
            return 1;
        if(n<0) {
            x = 1/x;
            n = -n;
        }
        if (n%2!=0)
            return x * myPow(x,n-1);
        return myPow(x*x,n/2);
    }
}
python
class Solution(object):
    def myPow(self, x, n):
        """
        :type x: float
        :type n: int
        :rtype: float
        """
        if n == 0:
            return 1
        if n < 0:
            x = 1 / x
            n = -n
        if n % 2:
            return x * self.myPow(x, n - 1)
        return self.myPow(x * x, n / 2)

快速幂

计算 x n x^ n xn 通常需要 n n n 次乘法, 时间复杂度为 O ( n ) O(n) O(n) , 当 n n n 非常大的时候, 运算效率很低.

快速幂是通过把 n n n 转化为二进制来实现的. 例如: 计算 x 14 x^{14} x14, 14 可以用二进制表示为:

14 = ( 1110 ) 2 = 1 ∗ 2 3 + 1 ∗ 2 2 + 1 ∗ 2 1 + 0 ∗ 2 0 14 = (1110)_ 2 = 1 * 2^3 + 1 * 2^2 + 1 * 2^1 + 0 * 2^0 14=(1110)2=123+122+121+020

那么对应的乘法可以表示为:

x 14 = x 2 3 ∗ x 2 2 ∗ x 2 1 x^{14} = x^{2 ^3} * x^{2^2} * x^{2 ^1} x14=x23x22x21

转换后乘法运算次数减少, 每次计算 x 2 n x^{2^n} x2n, 再决定是否将这个数字加入到最终结果里面去. 代码如下:

python
class Solution:
    def myPow(self, x: float, n: int) -> float:
        res = 1
        if n < 0:
            n = -n
            x = 1/x
        while n:
            if n & 1:
                res *= x
            x *= x
            n = n >> 1
        return res

java
class Solution {
    public double myPow(double x, int n) {
        double res = 1.0;
        long b = n; // 防止 int 溢出, 使用 long
        if(b<0) {
            x = 1/x;
            b = -b;
        }
        while (b >0) {
            if ((b&1) ==1)
                res *= x;
            x *= x;
            b >>= 1;
        }
        return res;
    }
}
  • 如果你觉得本文对你有帮助,请点赞👍支持
  • 如果有疑惑或者表达不到位的额地方 ,请在下面👇评论区指出
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值