Pow(x, n)

本文详细阐述了在处理大数幂运算时,从直觉递归方法到优化为二分法的过程。通过比较两种算法的时间复杂度,展示了算法效率的重要性。进一步介绍了如何通过优化避免重复计算,最终实现高效解决问题的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这题顾名思义,要求实现double x的n次方,当然n可正可负。

上路想都不想觉得太简单了然后唰唰唰写了一个最无脑直接分递归版本:

//version 1.0
class Solution {
public:
    double pow(double x, int n) {
     
        if(n==0)
            return 1.0;
            
        if(n>0)
            return x*pow(x,n-1);
        
        if(n>0)
            return (1/x)*pow(x,n+1);
    }
};
结果显示:

Time Limit Exceeded. Last executed input:0.00001, 2147483647

。。。。。。

仔细一看才发现是由于这种递归时间复杂度为O(n),所以当n非常大的时候,时间会线性增加然后导致出现这种error。

这时候又是上网一同乱搜发现主流的解决方法是用二分法[1]:

xn = xn/2 * xn/2 * xn%2
这种算法的时间复杂度为O(logN),明显要比O(N)好多了。

于是唰唰唰又写了一个版本:

//version 2.0
class Solution {
public:
    double pow(double x, int n) {
       
       if(n==0)
        return 1;
       if(n==1)
        return x;
       if(n==-1)
        return 1/x;
        
       if(n>0)
        return pow(x,n/2)*pow(x,n/2)*pow(x,n%2);
        
       if(n<0)
        return pow(x,n/2)*pow(x,n/2)*pow(x,n%2);
    }
    
};
结果显示:

Time Limit Exceeded. Last executed input:0.00001, 2147483647
。。。 .。。。WTF!!!
后来找到一个也是二分法的版本[2]后才发现问题,在version2.0中每次return都要算两次pow(x,n/2),这样其实复杂度为 O(2*logN),对于超大的N还是超时了。
然后简单用了一个临时变量tmp解决了问题:
//version 3.0
class Solution {
public:
    double pow(double x, int n) {
       
       if(n==0)
        return 1;
       if(n==1)
        return x;
       double tmp=pow(x,abs(n/2));
        
       if(n>0)
        return tmp*tmp*pow(x,n%2);
        
       if(n<0)
        return 1/(tmp*tmp*pow(x,abs(n)%2));
       
    }
    
};
Submission Result: Accepted (20ms)
 嘿嘿~~

小结(貌似第一次用这么正式的小结啊,不过感觉这道理训练的意义很大)
第一:看起来简单的题目其实不一定简单,容易犯想当然的低级错误;
第二:算法的重要性,一个好的算法要比一个普通的算法(两个都是正确的)效率要高很多很多;
第三:细节很重要,一个不小心忽略了细小的地方很有可能会导致结果的巨大差距。


参考:
[1] http://blog.unieagle.net/2012/08/23/leetcode%E9%A2%98%E7%9B%AE%EF%BC%9Apowxn/
[2] http://blog.youkuaiyun.com/havenoidea/article/details/12853985







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值