LeetCode-50-powx-n

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

示例 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] 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/powx-n
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解法1:

func myPow(x float64, n int) float64 {
    if n >= 0 {
        return pow(x, n)
    }
    return 1.0 / pow(x, -n)
}

// 按照定义x**n = n个x相乘
func pow(x float64, n int) float64 {
    y := 1.0
    for i := 0; i < n; i++ {
        y = y * x
    }
    return y
}

打完收工,结果

执行结果:超出时间限制
最后执行的输入:
0.00001
2147483647

改进

上述算法做了n次乘法,直接超时了,能不能减少运算量呢

思考:

  • 如果n是2的倍数,\(x^{2k}=x^k*x^k\),也就是可以减少一半的计算量,这个称之为快速幂
  • 如果n不是2的倍数,\(x^{2k+1}=x^{2k}*x\),可以转化成第一种情况
func myPow(x float64, n int) float64 {
    if n >= 0 {
        return pow(x, n)
    }
    return 1.0 / pow(x, -n)
}

func pow(x float64, n int) float64 {
    // 递归出口
    if n == 0 {
        return 1.0
    } else if n == 1 {
        return x
    }

    // x^{2k}   = x^{k}     * x^{k}
    // x^{2k+1} = x^{2k}    * x
    if n % 2 == 0 {
        ans := pow(x, n / 2)
        return ans * ans
    } else {
        return x * pow(x, n - 1)
    }
}

执行结果:通过
执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
内存消耗:2 MB, 在所有 Go 提交中击败了66.05%的用户

能不能更给力一点

上述解法使用了递归,需要额外的栈空间,可以改成迭代

  • 我们可以把n拆分 \(n = 2^i + 2^j + 2^k + ... + 2^0\)
  • \(x^n = x^{2^i + 2^j + 2^k + ... + 2^0} = x^{2^i} * x^{2^j} * x^{2^k} * ... * x^{2^0}\)
  • 例如 \(9 = b1001 = 1*2^3 + 0*2^2 + 0*2^1 + 1*2^0\),可得\(x^9=x^8*x^1\)
// 非递归的解法
func pow(x float64, n int) float64 {
    ans := 1.0
    for i := n; i != 0; i /= 2 {
        if i % 2 != 0 {
            ans *= x
        }
        x *= x
    }
    return ans
}

执行结果:通过
执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
内存消耗:2 MB, 在所有 Go 提交中击败了100.00%的用户

posted @ 2020-08-18 14:48  HiroSyu  阅读(59)  评论(0编辑  收藏  举报