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,就不用判断边界辣

  • 相关阅读:
    Atitit  Uncaught (in promise) SyntaxError Unexpected token < in JSON at position 0
    Atitit  验证 数字验证 非空验证的最佳算法  h5
    Atitit 转移特效attilax总结
    Atitit Loading 动画效果
    Atitit 项目管理 提升开发效率的项目流程方法模型 哑铃型  橄榄型 直板型
    Atitit hibernate3 hinernate4 hibernate5新特性attilax总结
    Atitit js es5 es6新特性 attilax总结
    Atitit mybatis 3 3.2 3.3  3.4 新特性attilax总结
    Atitit spring 3.0 3.1 3.2 4.0 4.3 5.0 新特性
    Atitit jquery  1.4--v1.11  v1.12  v2.0  3.0 的新特性
  • 原文地址:https://www.cnblogs.com/nanf/p/binarysearch.html
Copyright © 2011-2022 走看看