ACM 选手图解 LeetCode Pow(x,n)

简介: ACM 选手图解 LeetCode Pow(x,n)

大家好呀,我是帅蛋。


今天解决 Pow(x,n),这是分治算法的第一道实战题,先给小婊贝们找找感觉。

640.jpg

话不多说,让我们来搞起~

640.png



   LeetCode 50:Pow(x,n)



题意


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



示例


输入:x = 2.00000,n = 10

输出:1024.00000

输入:x = 2.00000,n = -2

输出:0.25000

提示


  • -100.0 <= x <= 100.0
  • -2^31 <= n <= 2^31 - 1
  • -10^4 <= x^n <= 10^4


题目解析


难度中等,针对这道题,有很多种经典解法,分治算法是其中一种。


如果还不了解分治算法,可以先看下面这篇文章:


ACM 选手带你玩转分治算法!


分治算法由“分”和“治”两部分组成,但是它主要包括 3 个过程


  • 划分(Divide)
  • 求解(Conquer)
  • 合并(Combine)


其中:


划分(Divide):将原问题划分为规模较小的子问题,子问题相互独立,与原问题形式相同。


求解(Conquer):递归的求解划分之后的子问题。


合并(Combine):这一步非必须。有些问题涉及合并子问题的解,将子问题的解合并成原问题的解。有的问题则不需要,只是求出子问题的解即可。

640.png


说白了就是先找找拆分到最小规模问题时怎么解,然后再瞅瞅随着问题规模增大点问题怎么解,最后就是找到递归函数,码出递归代码即可


根据 n 的取值范围,它可能分为 3 种情况:n 为负数、n 为正数时又分为 n 为奇数、n 为偶数。


所以整个的解题步骤就很明确:


(1) 划分


划分就是拆解到问题的最小规模,这里可以用一点点二分的思想。


n 为偶数时,x^n 可以转换为 x 的 n/2 相乘,然后 x 的 n/2 又可以转换为 x 的 n/4 相乘,...,直到转换成 x^1。


n 为奇数时,先拆出一个 x,n-1 为偶数,再以上面同样的逻辑去分,只是最后记得把拆出来的 x 带上。


n 为负数时,-n 是正数,x 的 n 次方,相当于就是 x^ (-n) ,按照上面求完以后取个倒数。


(2) 求解


递归的求解划分之后的子问题。


最小的情况就是 n = 1 或者 n = 0,此时的值为 x 或者 1。


(3) 合并


一步步的向上合并,合并出最后的解。


图解


x = 2.00000,n = 10 为例。


先是自顶向下的分解问题,分解如下图所示:

640.png


之后按照自底向上的方式合并解。


此解法需要计算 x 的 n 次方,x 的 n/2 次方,x 的 n/4 次方,...,x 的 1 次方,所以时间复杂度为 O(logn)


虽然分治算法没有直接分配额外的数组空间,但是在递归过程中调用了额外的栈空间,分治算法相当于每次将当前问题拆成了两部分,n 在变为 1 之前需要进行 O(logn) 次递归,所以空间复杂度也为 O(logn)


代码实现


Python 代码实现


class Solution:
    def myPow(self, x: float, n: int) -> float:
        if n == 0:
            return 1
        if n == 1 or x == 1.0:
            return x
        # 如果 n 为负数,先求 x^n,再取倒数
        if n < 0:
            return 1 / self.myPow(x, -n)
        # 如果 n 为奇数
        if n % 2:
            return x * self.myPow(x, n - 1)
        # 如果 n 为偶数
        return self.myPow(x * x, n / 2)



Java 代码实现

class Solution {
    public double myPow(double x, int n) {
        if (n == 0){
            return 1;
        }
        if (n == 1 || x == 1.0){
            return x;
        }
        if (n < 0){
            return 1 / x * myPow(1 / x, -(n + 1));
        }
        int a = n / 2;
        int b = n % 2;
        return b == 0 ? myPow(x * x, a) : x * myPow(x * x, a);
    }
}




图解 Pow(x,n) 到这就结束辣,虽然是道中等难度的题,是不是感觉还挺简单的?


要是因此你就觉得分治算法也没啥难的,那你就是 too young too simple。


这种事情知道了答案就很简单,难的是推导的公式的过程


这个没有捷径,只能多思考多练习,要加油呀!


我是帅蛋,我们下次见!

相关文章
|
6月前
|
Java
Leetcode 372. Super Pow
真正的解法其实思路很简单,我随便举个例子就很容易理解了,假设要求(123^4567)%1337,只需要把这个幂式子分解成几个层次,然后把球模加到每一层中间就很容易计算出来了。
25 0
|
11月前
|
算法 安全 Swift
LeetCode - #50 Pow(x, n)
不积跬步,无以至千里;不积小流,无以成江海,Swift社区 伴你前行。如果大家有建议和意见欢迎在文末留言,我们会尽力满足大家的需求。
LeetCode 372. Super Pow
你的任务是计算 ab 对 1337 取模,a 是一个正整数,b 是一个非常大的正整数且会以数组形式给出。
49 0
LeetCode 372. Super Pow
LeetCode 50. Pow(x, n)
实现pow(x,n),即计算x的n次方
61 0
LeetCode 50. Pow(x, n)
|
存储 机器学习/深度学习 算法
LeetCode 49字母异位词分组&50pow(x,n)&51八皇后
给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
98 0
LeetCode 49字母异位词分组&50pow(x,n)&51八皇后
|
算法 Java C++
LeetCode(算法)- 50. Pow(x, n)
LeetCode(算法)- 50. Pow(x, n)
141 0
LeetCode(算法)- 50. Pow(x, n)
|
Java 数据安全/隐私保护 Python
ACM 选手图解 LeetCode 验证二叉搜索树
ACM 选手图解 LeetCode 验证二叉搜索树
ACM 选手图解 LeetCode 验证二叉搜索树
|
算法 Java Python
ACM 选手图解 LeetCode 二叉搜索树中的搜索
ACM 选手图解 LeetCode 二叉搜索树中的搜索
ACM 选手图解 LeetCode 二叉搜索树中的搜索
|
存储 Java Python
ACM 选手图解 LeetCode 二叉树的层平均值
ACM 选手图解 LeetCode 二叉树的层平均值
ACM 选手图解 LeetCode 二叉树的层平均值

热门文章

最新文章