zoukankan      html  css  js  c++  java
  • 二分

    该面对的总是要面对
    LeetCode34. 在排序数组中查找元素的第一个和最后一个位置
    题意是,在某个排序数组里找到target的第一次出现和最后一次出现。

    有两种解法

    第一种 [l,r]

            while(l<=r)
            {
                int mid = (l+r)/2;
                if(nums[mid]<target) l = mid+1;
                else r = mid-1;
            }
            a[0] = l;
            if((a[0]==nums.size())||nums[a[0]]!=target) a[0] = -1;
    

    由于 [l,r]

    1. 合法区间
      把问题转换为对合法区间的切分,在寻找左端点的情况下,相当于<target为合法,>=target为不合法。当mid值小于target时,说明此时l到mid都是合法的(包括mid)因此将l右移缩小范围。当mid大于等于target时,说明l到mid不合法,可以舍弃,使r = mid-1(即一个有可能的合法值)。

    2. 边界问题
      二分到最后l=r,(l+r)/2=l=mid,此时

      • 若合法:l=mid+1,结果就是l成为了不合法的那一个(因为mid也就是r合法)
      • 若不合法:r=mid-1,l不变,l依旧不合法。

      此时l=r+1。找到的最终合法值是r,在此题中就是第一个target的左边那一个,所以理论上l应该是第一个target。

    3. 若查找失败
      如果停在了数组内部,那么找到的r依旧是比target小一点的那一个,但nums[l]!=target。
      如果全部数字都大于target,依旧可以用nums[l]!=target。
      如果全部数字小于target此时l应该越界了,判断是否等于n即可。

    对右边端点的查找同理,合法区间变为<=target和>target,最终l非法r合法。找到的最大一个target是r,l是比target大一点点那个。

            l = 0, r = nums.size()-1;
            while(l<=r)
            {
                int mid = (l+r)/2;
                if(nums[mid]<=target) l = mid+1;
                else r = mid-1;
            }
            a[1] = r;
            if(l==0||nums[a[1]]!=target) a[1] = -1;
    

    查找失败的情况有所不同,因为最终判断合法是通过判断nums[pos]?=target,所以在这里应该用r来判断,r超出数组范围的情况就是r=-1,l=0。

    第二种 [l,r)

    在区间选择上,天生l合法r不合法,因此当l=r(冲突)时退出循环。

            int l = 0, r = n;
            while (l < r) {
                int mid = (l + r) / 2;
                if (nums[mid] < target) l = mid + 1;
                else r = mid;
            }
            if (r == n || nums[r] != target) return {-1, -1};
    
    1. 合法区间
      在转移的时候r=mid,而不是mid-1,因为此时mid已经验证不合法,然后r刚好是一个不合法值。感觉就是l代表合法阵营,r代表不合法阵营,在搜索他们那个分界点,更直观?

    2. 边界问题
      二分到最后l=r-1,(l+r)/2=l=mid,此时

      • 若l合法:l+1,最终l不合法了
      • 若l不合法:r=l,l不变,l依旧不合法。

      此时l=r=第一个target。

    3. 若查找失败
      如果停在了数组内部,nums[l]!=target。
      如果全部数字都大于target,依旧可以用nums[l]!=target。
      如果全部数字小于target此时l应该越界了,判断是否等于n即可。

    实际上可以假装nums[-1]的坐标有一个-inf,nums[n]有一个inf,就不用判断边界辣

  • 相关阅读:
    如何在百度网盘中批量添加好友,批量创建群组,导出群链接等
    批量对百度网盘好友及群组发文字消息及分享文件
    百度网盘禁止查看别人分享主页的资源收集解决办法
    C#调用windows API实现 smallpdf客户端程序进行批量压缩
    邓西百度网盘目录导出工具
    .net sqlite 内存溢出 问题的分析与解决。
    移动呼死你防护业务白名单批量导入工具
    如何拦截电话轰炸、短信轰炸
    以技术原理入手从根本上拦截屏蔽解决响一声电话呼死你炸你妹电话轰炸短信轰炸,远离电话短信骚扰
    邓西百度网盘批量分享工具
  • 原文地址:https://www.cnblogs.com/nanf/p/binarysearch.html
Copyright © 2011-2022 走看看