小白学算法之折半(二分)查找

177 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情

通过折半算法,可以大大减少运算时耗--无苦邪

折半查找也就是二分查找,大家可能第一次认识它的时候就是在学习c语言时,老师喊我们写的一个猜大小算法

有一个1-100内的数字,请你输入你认为的数字

我们可以从1开始输入,一直输入到100,幸运的话需要猜的数字就1,运气差没准就是100.但该算法还会提示你所给的数是大了还是小了,所以你可以根据它提示的大小来舍去了一部分区间

但如何去规定区间呢,就使用到了二分

猜测1-100的数,我们就可以选择中间的数字

50 大了,那么此时区间就是0-50;小了区间就是50-100

有比较帅的读者问为什么是1/2而不是1/4,3/4呢,

因为均值,你不知道你所求的数在左边还是右边,所以你需要设定一个均区间

2.例题实操

50. Pow(x, n) - 力扣(LeetCode)

实现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;
    }
};