开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情
通过折半算法,可以大大减少运算时耗--无苦邪
折半查找也就是二分查找,大家可能第一次认识它的时候就是在学习c语言时,老师喊我们写的一个猜大小算法
有一个1-100内的数字,请你输入你认为的数字
我们可以从1开始输入,一直输入到100,幸运的话需要猜的数字就1,运气差没准就是100.但该算法还会提示你所给的数是大了还是小了,所以你可以根据它提示的大小来舍去了一部分区间
但如何去规定区间呢,就使用到了二分
猜测1-100的数,我们就可以选择中间的数字
50 大了,那么此时区间就是0-50;小了区间就是50-100
有比较帅的读者问为什么是1/2而不是1/4,3/4呢,
因为均值,你不知道你所求的数在左边还是右边,所以你需要设定一个均区间
2.例题实操
实现pow函数
做这题有帅读者就直接套pow函数,这显然不是本题的意思😂,是让你实现,以下给出三种讲解
1)暴力
老样子上来不会先暴力,结果超时不可取,但给出一个实现思路
//暴力
class Solution {
public:
double myPow(double x, int n) {
double res=1.0;
if(n<0)
{
x=1/x;
n=-n;
}
for(int i=0;i<n;i++)
{
res*=x;
}
return res;
}
};
1.00000
2147483647
超出时间限制
2)递归
思路:
假如是pow(2,5) 那么就是2*2*2*2*2,我们人的思路就是
2*2=4 -->4*4*2=32
递归
class Solution {
public:
double num(double x,long long N)
{
if(N==0)
{
return 1.0;
}
double y=num(x,N/2);
//如果是奇数就会多出一个,就要多*x
return N%2?y*y*x:y*y;
}
double myPow(double x, int n) {
//n的范围问题,将其扩大
long long N=n;
//n<0,就转变为倒数,再将N转为zheng'shu
return N>=0?num(x,N):1/num(x,-N);
}
};
3)这就是本章的方法折半查找
其实本题思路与上面的递归一样
先判断指数是否为奇数,pow(2,5)=4*4*2
本题结果是浮点数,所以设了一个res=1.0
指数为奇数先让res*2
然后让底数自乘2*2=4,
循环的循环条件i/=2,举例便是
2*2*2*2*2*2*2*2
4*4*4*4
16*16 每次都是分成了一半进行组合了,所以末尾循环是进行二分,而不是--了
class Solution {
public:
double myPow(double x, int n) {
double res=1.0;
//注意终止条件
for(int i=n;i!=0;i/=2)
{
//先判断总次数是否为奇数,奇数先乘以一个
if(i%2)
{
res*=x;
}
//然后进行
x*=x;
}
return n>0?res:1/res;
}
};