码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 二分查找一个数首次与最后出现的位置


    [题目描述]

    查找顺序数组中某个数首次或最后一次出现的位置。

    首次出现:

    public class BinarySearch {
        public static int left(int key, int[] a) {
            int lo = 0;
            int hi = a.length - 1;
            while (lo < hi) {
                int mid = lo + (hi - lo) / 2;
                if (key < a[mid]) hi = mid - 1;
                else if (key > a[mid]) lo = mid + 1;
                else hi = mid;
            }
            if (a[hi] == key) //或 lo
                return hi;
            return -1;
        }
    
        public static void main(String[] args) {
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    1. hi = mid找到下标时不返回,存入 hi, 逐步收缩右边界,找不到时则按照传统二分计算。

    2. 循环结束条件。

      退出前一步可能 mid = lo 或mid = (hi - lo) / 2 。

      mid = (hi - lo) / 2 时:

      • 如果 a[mid] = key,hi = mid,也就是下一种情况(mid = lo )。
      • 如果 a[mid] < key,lo = hi,退出循环。

      mid = lo 时:

      • 如果 a[mid] = key,hi = mid = lo,退出循环。
      • 如果 a[mid] < key,lo = hi,退出循环。

      综上,退出循环时总有 `lo = hi`,所以,循环结束条件如果设置成 <= 将会无限循环。
    3. 循环退出时还未判断 hi 处的值,所以 if (a[hi] == key)用来判断上面循环未判断的 hi 处的值是否等于 key。因为 lo = hi 所以此处也可换为 if (a[lo] == key)。

    最后一次出现:

    	public static int right(int key, int[] a) {
            int lo = 0;
            int hi = a.length - 1;
            while (lo < hi) {
                int mid = lo + (hi - lo) / 2 + 1;
                if (key < a[mid]) hi = mid - 1;
                else if (key > a[mid]) lo = mid + 1;
                else lo = mid;
            }
            if (a[lo] == key) //或 hi
                return lo;
            return -1;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    利用对称性(便于理解),类比上面的算法,很容易想到将else hi = mid;换成else lo = mid;,将下标存入 lo,收缩左边界。

    但此时有一点不对称,就是计算 mid 时是取整计算,去掉小数点后的数,如果要对称的话就要在原始 mid 的基础上加 1。即 int mid = lo + (hi - lo) / 2 + 1;

  • 相关阅读:
    六月集训(26)并查集
    06.Oracle数据备份与恢复
    【漏洞情报】泛微 E-Cology KtreeUploadAction 文件上传漏洞
    2022年全球市场混凝土脱模剂总体规模、主要生产商、主要地区、产品和应用细分研究报告
    【计算机网络】VLAN原理和配置
    04 如何寻找嵌入式各行业项目,嵌入式行业信息网站大全
    九、2023.10.3.Linux(end).9
    使用FPGA实现逐级进位加法器
    【AGC】云托管新建站点时间过长的问题排查方法
    (GCC)STM32基础详解之全局资源的使用
  • 原文地址:https://blog.csdn.net/weixin_45773137/article/details/126061447
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号