• 二分法,三分法


    二分法

    二分法用来在有序数列中查找某个值是否存在

    但其实,二分最广泛的应用不是查找某个值,而是二分答案+check

    1.先将区间(左闭右开,不然可能会死循环)二分,每个区间的长度为1/2(right-left)

    2.如果mid能满足题目要求,那么使left变为mid+1,否则使right变为mid

    因为如果mid满足条件,那么[l,mid]区间肯定都满足条件,增大要求,否则减小要求

    bool check(int x){} // 检查是否可行 
    while(l<r)
    {
        int mid=(l+r)/2;
        if(check(mid)) l=mid+1;
        else r=mid;
    }

    最终答案为l-1

    分析一下最终答案是什么,由于只要能进if,则l等于满足条件的数+1,则最后二分出来的数值为最大的满足条件的数+1,即ans要-1

    最终二分出来的数值为

    若if那一行写的是l=mid+1,则数值为第一个能进不了if(条件)的数(即不满足条件),

    否则 若写的是r=mid,即为第一个能进得了if(条件)的数(即满足条件)

    三分法

    在区间内用两个mid将区间分成三份,这样的查找算法称为三分查找,也就是三分法,三分法常用于求解单峰函数的最值。  

    三分法和二分法有些类似,二分处理的是递增/减的函数,而三分处理的是先递增后递减(或相反)的函数(单峰函数)的最值

    1.先将区间三分,每个区间的长度为1/3(right-left)

    2.比较mid1和mid2的函数值谁大,如果mid1更大,right改为mid2,否则left改为mid1

    3.若区间长度小于5,特判避免死循环

    算法的正确性:
    1、lmid与rmid在最值的同一侧。由于单峰函数在最大值(最小值)任意一侧都具有单调性,因此,lmid与rmid中,更大(小)的那个数自然更为靠近最值。此时,我们远离最值的那个区间不可能包含最值,因此可以舍弃。
    2、lmid与rmid在最值的两侧。由于最值在中间的一个区间,因此我们舍弃一个区间后,并不会影响到最值
    int ans=-1;
    int f(int x){}//求函数值 
    while(1)
    {
        if(r-l<5)
        {
            for(int i=l;i<=r;i++)ans=max(ans,f(i));
            break;
        }
        int lm=l+(r-l)/3,rm=r-(r-l)/3;
        if(f(lm)<f(rm))l=lm;
        else r=rm;
    } 

    最终答案为ans

  • 相关阅读:
    IoC~MVC3+EF+Autofac实现松耦合的系统架构 [转载]
    Ioc容器Autofac系列 向导
    依赖注入框架Autofac的简单使用 转载
    学 Win32 汇编[30] 条件及循环伪指令: .IF、.WHILE、.REPEAT 等
    学 Win32 汇编[31] 结构与联合
    在 API 函数中使用 PChar 参数的几种方法
    关于 "高位" 与 "低位" 回复 "Lovemit" 的问题
    如何把类中的方法做参数 回复 "林Lin☆☆" 的问题
    一个拼图工具的制作思路 回复 "AlwaysBug" 的问题
    简单的 "双缓冲" 绘图的例子 回复 "TookiQ" 的问题
  • 原文地址:https://www.cnblogs.com/lher/p/7481554.html
Copyright © 2020-2023  润新知