• ACwing算法基础课听课笔记(第一章,基础算法一)(二分)


      二分法:

        在看这个视频前,我对于二分法是一头雾水的,又加上这个算法我个人很容易写错emm...。视频提到ACwing上的一道题,我用自以为聪明的方法去做,结果TLE了,实在丢人,不说了,开整!

        对于例题 789:数的范围,寻找一个数前后第一次与最后一次出现的坐标。我们需要这个模板:

        

        数组定为number[];

        (1)来看第一种情况:如图,假设两个点分别是最先与最后出现的位置。求第一次x出现的位置实际上就是(1)这种情况。那么我们定一个条件

                mid=(l+r)>>1  

                if(number[mid]在a中)  

                  r=mid;  区间变为[L,mid], 因为mid处可能是答案,所以mid不要加一也不要减一。

                  else(落在b中)  

                      l=mid+1;   区间变为[mid+1,R]  

        (2)来看第二种情况:如图,就是求x最后一次出现的位置了。依然是

                 int mid=(l+r+1)>>1;   

                 if(number[mid]在b中)  

                    l=mid    区间变为[mid,R],mid不要动因为mid处可能是答案

                else    

                    r=mid-1  因为mid处肯定不是答案,所以要减一,区间变为[L,mid-1];

        但是注意要注意(2)中的(L+r+1)>>1,因为如果  l=r-1时,式子不加一会出现mid=L+1/2,因为向下取整,所以mid=L,进入if后会一直求出区间[L,R]造成死循环,而(1)就不会出现。

        综上,有以下两个模板,分别对应不同的情况

    //区间[L,R]被分成[L,mid]和[mid+1,R]时
    int
    bsearch_1(int l,int r) { while(l<r) { int mid=l+r >>1; if(check(mid)) r=mid; else l=mid+1; } }
    //区间[L,R]被分成[L,mid-1]和[mid,R]时
    int bsearch_2(int l,int r) 
    {
      while(l<r)
      {
        int mid=l+r+1 >>1;
        if(check(mid))
          l
    =mid;
       
    else
          r
    =mid-1; }
     }

       然后上789代码  :  

    #include<iostream>
    const int maxn=1e5+10;
    using namespace std;
    
    int a[maxn];
    int n,k;
    int main()
    {
        cin>>n>>k;
        for(int i=0;i<n;i++)
            cin>>a[i];
        while(k--)
        {
            int x;
            cin>>x;
            int l=0,r=n-1;
            while(l<r)
            {
                int mid=(l+r)>>1;
                if(a[mid]>=x)
                {
                    r=mid;
                }
                else
                {
                    l=mid+1;
                }
            }
            if(a[l]!=x)
                cout<<"-1 -1"<<endl;
            else
            {
                cout<<l<<' ';
                int l=0,r=n-1;
                while(l<r)
                {
                    int mid=(l+r+1)>>1;
                    if(a[mid]<=x)
                    {
                        l=mid;
                    }
                    else
                        r=mid-1;
                }
                cout<<r<<endl;
            }
        }
    }

        再来个手动开方嘿嘿,二分法:

        

    #include<iostream>
    using namespace std;
    #include<cstdio>
    int main()
    {
        double x;
        while(cin>>x)
        {
            double l=0,r=x;
            while((r-l)>1e-6)//精度不够再加,可以时1e-8
            {
                double mid=(l+r)/2;
                if(mid*mid>x)
                    r=mid;
                else
                    l=mid;
            }
            printf("%lf
    ",l);
        }
    }

      

      开三次方:ACWING  790

      

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    using namespace std;
    int main()
    {
        double x;
        while(cin>>x)
        {
            double l,r;
            if(x>=0)
                l=0,r=x;
            else
                l=x,r=0;
            while(fabs(r-l)>1e-8)
            {
                double mid = (l+r)/2;
                if(mid*mid*mid>x)
                    r=mid;
                else
                    l=mid;
            }
            printf("%lf
    ",l);
        }
    }
  • 相关阅读:
    css常用字体
    多行文本显示省略号,点击展开隐藏
    某个公司采用公用电话传递数据,数据是四位的整数,在传递过程中是加密的, 加密规则如下:每位数字都加上5,然后用除以10的余数代替该数字,再将第一位和第四位交换, 第二位和第三位交换,请编写一个函数,传入原文,输出密文
    编写一个函数,计算任意两个数字之间所能组成的奇数个数,数字必须是个位数。 比如:计算0~3之间能组成的奇数是: 01、03、13、21、23、31
    Redis(一) 数据结构与底层存储 & 事务 & 持久化 & lua
    IO多路复用之Reactor
    IO多路复用之select poll epoll
    五种IO模型
    kafka(五) 流式处理 kafka stream
    kafka(二) 高性能技术分析
  • 原文地址:https://www.cnblogs.com/liyexin/p/11789156.html
Copyright © 2020-2023  润新知