Leetcode 50-Pow(x, n)

实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn )。
在这里插入图片描述

题解

题解转载自编程文青李狗蛋

本题很容易让人想到x^n= x^ n/2 *x^ n/2这个操作,但是如何从底到上以及终止条件是什么呢?这时候就可以用到分治(一种递归),自底向下的分解问题,求解,并向上合并

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

划分(Divide)
求解(Conquer)
合并(Combine)
其中:

  1. 划分(Divide):将原问题划分为规模较小的子问题,子问题相互独立,与原问题形式相同。
  2. 求解(Conquer):递归的求解划分之后的子问题。
  3. 合并(Combine):这一步非必须。有些问题涉及合并子问题的解,将子问题的解合并成原问题的解。有的问题则不需要,只是求出子问题的解即可。
    在这里插入图片描述
    说白了就是先找找拆分到最小规模问题时怎么解,然后再瞅瞅随着问题规模增大点问题怎么解,最后就是找到递归函数,码出递归代码即可。

根据 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 为例。

先是自顶向下的分解问题,分解如下图所示:
在这里插入图片描述
之后按照自底向上的方式合并解。

class Solution {
    //如果是偶数 x^n=x^(n/2)*x^(n/2)
    //如果是奇数 x^n=x^(n/2)*x^(n/2)*x
    //终止条件 n==1||n==0
    //还要特殊考虑x<0的情况
    public double myPow(double x, int n) {
        return n>0?recur(x,n):1.0/recur(x,n);
    }

   public double recur(double x, int n) {
        if(n==1) return x;
        //一定要是1.0,避免返回int类型
        if(n==0) return 1.0;
        //存值避免后续多次计算
        double temp=recur(x,n/2);
        if(n%2==0) return temp*temp;
        else  return temp*temp*x;
    }
}

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值