🎉前言🎉
在这个系列中,博主准备分享每日在万人千题社区打卡学习的算法。博主也是小白,因此也很能理解新手在刷题时的困惑,所以关注博主,每天学习一道算法吧。同时也欢迎大家加入万人千题习活动,正所谓:一个人可以走的很快,但一群人才能走的更远。
万人千题打卡社区https://bbs.csdn.net/forums/hero?category=0https://bbs.csdn.net/forums/hero?category=0
目录
一、知识精讲
【知识精讲总结于下面这篇文章,不大懂的可以看看】快速幂算法(全网最详细地带你从零开始一步一步优化)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);
}