zoukankan      html  css  js  c++  java
  • 对于二分的理解

    看了曦行夜落-浅谈二分的边界问题后深有感触,特此写下此篇博客以作梳理。

    简介

       二分是一种求取极值的算法,通常是已知所求答案的范围,然后根据一系列约束条件对其进行控制使得到的答案最优。二分答案需要满足单调性,举个例子来看,我们要完求完成任务的最小代价(范围为1到100),我们考虑中间值50:

          如果以50的代价可以完成任务,那么,我们以51~100的代价显然也可以完成任务。

          如果以50的代价不能完成任务,那么,我们以0~50的代价就都不能完成任务。

      正是因为这种单调性,才使得二分可以在log2n的时间内完成查找工作。

    进行原理

      我们接着考虑上面的例子,我们可以发现:

          如果以50的代价可以完成任务,那么,我们以51~100的代价显然也可以完成任务。则,我们需要在0~50中去寻找更优的满足条件的解。

          如果以50的代价不能完成任务,那么,我们以0~50的代价就都不能完成任务。则,我们只能通过去牺牲数据,在51~100中去需找满足条件的解。

      这就是二分的进行机制,由此,我们可以发现,二分中真正重要的地方是中间条件的取值。

    对于二分中间值的讨论

      二分的中间值是二分过程中最容易出锅的地方, 对于是应该取mid + 1还是mid - 1又或是mid常常让人混乱,这里我们对其进行一定的梳理。

      二分中的主要思想有以下三种:

      1. l 和 r 所代表的”成本值”均可行(即当前讨论的区间为[ l, r]),且存在一个最优解ans。
      2. l 和 r 所代表的“成本值”均可行,最后答案是 l 和 r。
      3. l 和 r 所代表的“成本值”只有 l 可行而 r 不可行(即当前讨论的区间是[l, r ) ),最终的答案是 l。

      我们对前两种算法进行模板归纳

        思想1:储存答案

    for (;l<=r;)
    {
        int mid=(l+r)/2;
        if (check(mid))
        {
            ans=mid;
            r=mid-1;
        }
        else l=mid+1;
    }
    printf("%d",ans);

        结束条件是l > r 时停止循环,此时答案记录为ans。(依旧以上面举到的例子求大于条件的最小值)

        对于每次循环中的mid,都把当前的区间分为了三部分[l , mid - 1] , mid, [ mid + 1, r],这三部分中,我们根据mid处的值将问题分为两类。

      1. 当mid满足条件的时候,我们就把mid当作是的当前的最优解,然后去考虑[l, mid - 1]中有没有可以刷新当前最优解的更优解。
      2. 当mid不满足条件的时候,我们就考虑[mid + 1, r]中有没有可以满足条件的解。

        求大于的最小值则正好相反。

        思想2:不储存答案

    while (l<r)
    {
        int mid=(l+r)/2;
        if (check(mid)) r=mid
        else l=mid+1;
    }
    printf("%d",l); 

        结束条件是 (l == r),此时l 和 r 相同且都是最优解。(依旧以上面的例子求大于条件的最小值)

        对于每次循环中的mid,都把当前的区间分为了两部分[l, mid], [mid + 1, r],这两部分中我们根据mid的值将问题分为两类。

      1. 当mid满足条件的时候,我们把mid看作是一个可行解,根据二分的单调性我们可以知道[mid + 1, r]一定都满足条件且没有mid更优,所以我们可以得到更优的解一定是存在于[l, mid]中的。为什么要包括mid呢?我们可以这样来看,我们假设当mid就是满足条件的最优解而且这个区间中数的个数不只一个,如果我们只考虑[l, mid - 1]的话,就会因为漏解而使得最终答案错误。
      2. 当mid不满足条件的时候,根据单调性[l, mid]一定都不能满足条件,所以我们只需要在[mid + 1, r]中寻找满足条件的解即可。

        反过来,如果我们求的是小于条件的最大值时,对于每次循环中的mid, 都把当前区间分为了两部分[l, mid - 1],[mid, r],两部分。

    二分查找

      二分查找就是最经典的二分答案,我们对于一个有序序列,记录查找值为key的数, 而对于一个为key的数,我们既可以把他看作是满足大于条件的最小值,也可以看作是满足小于条件的最大值。

  • 相关阅读:
    122. Best Time to Buy and Sell Stock II
    121. Best Time to Buy and Sell Stock
    72. Edit Distance
    583. Delete Operation for Two Strings
    582. Kill Process
    indexDB基本用法
    浏览器的渲染原理
    js实现txt/excel文件下载
    git 常用命令
    nginx进入 配置目录时
  • 原文地址:https://www.cnblogs.com/2020pengxiyue/p/9372533.html
Copyright © 2011-2022 走看看