【跟着英雄学算法⑮】深入剖析二分快速幂——附Leercode刷题题解(C语言实现)

🎉前言🎉

       在这个系列中,博主准备分享每日在万人千题社区打卡学习的算法。博主也是小白,因此也很能理解新手在刷题时的困惑,所以关注博主,每天学习一道算法吧。同时也欢迎大家加入万人千题习活动,正所谓:一个人可以走的很快,但一群人才能走的更远。

 万人千题打卡社区https://bbs.csdn.net/forums/hero?category=0https://bbs.csdn.net/forums/hero?category=0


目录

一、知识精讲

 二、50.Pow(x,n)

⑤解决方法一:

⑥解决方法二:

⑥解决方法三:


一、知识精讲

 【知识精讲总结于下面这篇文章,不大懂的可以看看】快速幂算法(全网最详细地带你从零开始一步一步优化)https://blog.csdn.net/qq_19782019/article/details/85621386https://blog.csdn.net/qq_19782019/article/details/85621386

这是博主看了上面文章的总结,大家可以先看看上面的文章,总结为大家再次梳理一下思路

 二、50.Pow(x,n)

Pow(x,n)https://leetcode-cn.com/problems/powx-n/https://leetcode-cn.com/problems/powx-n/①题目呈现

 ②奇技淫巧

 🤣好了,不开玩笑了,切入正题

③解题分析:

我们完全可以套用知识精讲里的模板,只是不需要进行取模运算,因为题目已经限制了数据的范围,所以不用担心。但不同的是本题pow可以取到负数。那很简单啊,先当他是正数,最终结果为其倒数不就行了吗!真的是这样吗?

④坑点分析: 

结果是不行的,这也是这道题目最坑的地方。为什么呢?报错已经给你提示。你可能没有注意到,int的范围在-2147483648 ~ 2147483647之间,如果对n=-2147483648进行n=-n操作会造成溢出。

⑤解决方法一:

 对n先进行++处理后转为正数,最后结果取倒数。

double myPow(double x, int n)
{
    double ret = 1.0;
    if(n > 0)
    {
        while(n)
        {
            if(n & 1)
            {
                ret *= x;
            }
            n >>= 1;
            x *= x;
        }
    }
    else if(n < 0)
    {
        double tmp = x;
        n++;
        n = -n;
        while(n)
        {
            if(n & 1)
            {
                ret *= x;
            }
            n >>= 1;
            x *= x;
        }
        ret = 1 / (ret * tmp);
    }
    return ret;
}

被坑经历: 

遇到n为负数时不要先将x变成1/x,这样的话最后结果为0,而是应该对最后的结果取倒数,这样误差小很多。

 上面代码写的挺矬的,是为了便于大家理解😁(强行解释)。

⑥解决方法二:学习自         [解题报告]《算法零基础100讲》(第15讲)

转换成无符号整形就可以保存的下。

double myPow(double x, int n)
{
    double y = 1;    
    unsigned m;    
    if(n < 0)
    {    
        x = 1/x;
        m = -(unsigned int)n;
    }
    else m = n;
    while(m)
    {            
        if(m&1 == 1) y *= x;
        x *= x;
        m >>= 1;
    }
    return y;
}

 ⑥解决方法三:

不管n的正负,每次对n进行/2处理,不能是>>=1 哦

double myPow(double x, int n)
{
    if(n == 0)
        return 1;
    int flag;     //flag作为标记正负的变量
    double ans = 1.0;
   flag = n > 0?1: 0;
    
    while(n)
    {
        if(n & 1)
        {
            ans *= x;
        }
        x *= x;
        n /= 2;//这里不可以是n>>=1哦
    }
    return flag? ans:(1.0/ans);
}

  • 23
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 15
    评论
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罅隙`

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值