前言科普

第一篇二分搜索论文是 1946 年发表,然而第一个没有 bug 的二分查找法却是在 1962 年才出现,中间用了 16 年的时间。

2019 年的你,在面试的过程中能手写出没有 bug 的二分查找法么?

定义

在计算机科学中,二分查找(英语:binary search),也称折半搜索(英语:half-interval search)、对数搜索(英语:logarithmic search),是一种在有序数组中查找某一特定元素的搜索算法

搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;

如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。

如果在某一步骤数组为空,则代表找不到。

这种搜索算法每一次比较都使搜索范围缩小一半。

二分查找法代码

按照上面的定义,我们来尝试写一下二分查找法的代码。

public static int binary(int[] arr, int data) {
        int min = 0;
        int max = arr.length - 1;
        int mid;
        while (min <= max) {
            mid = (min + max) / 2;
            if (arr[mid] > data) {
                max = mid - 1;
            } else if (arr[mid] < data) {
                min = mid + 1;
            } else {
                return mid;
            }
        }
        return -1;
    }

现在问你,上面的代码有没有问题?哪段代码会出现 bug ?

请思考一分钟后再往下查看。

对于上面这段代码而言,问题出在第 6 行代码处:

mid = (min + max) / 2;

这句代码在 min 和 max 很大的时候,会出现溢出的情况,从而导致数组访问出错。

别看现在轻描淡写的指出了这个错误,但这个错误在当时可是存在了好些年。

那怎么改进呢?一般的做法是这样的:将加法变成减法。

public static int binary(int[] arr, int data) {
        int min = 0;
        int max = arr.length - 1;
        int mid;
        while (min <= max) {
            // 防止溢出
            mid =  min + (max - min) / 2;
            if (arr[mid] > data) {
                max = mid - 1;
            } else if (arr[mid] < data) {
                min = mid + 1;
            } else {
                return mid;
            }
        }
        return -1;
    }

还有一种更高逼格的写法,也是官方的二分搜索法的实现写法:使用 位运算

 public static int binary(int[] arr, int data) {
        int min = 0;
        int max = arr.length - 1;
        int mid;
        while (min <= max) {
            // 无符号位运算符的优先级较低,先括起来
            mid =  min + ((max - min) >>> 1);
            if (arr[mid] > data) {
                max = mid - 1;
            } else if (arr[mid] < data) {
                min = mid + 1;
            } else {
                return mid;
            }
        }
        return -1;
    }

希望通过今天的文章能帮助读者们在面试中手写对代码,毕竟,对于很多小公司来说,二分查找法会出现在他们的笔试题中的。

最新文章

  1. PAT (BL) 1001
  2. ajax 另外两种返回类型(json xml)
  3. 微信的公众号unionid
  4. [转]EntityFramework走马观花之CRUD(下)
  5. codeforce 604B More Cowbell
  6. DLL入门浅析(3)——从DLL中导出变量
  7. sh_脚本语法
  8. sublime Text3插件无法安装解决方法(提示There are no packages available installation)
  9. 我是这样发现ISP劫持HTTP请求的
  10. Kon-boot v2.5介绍与使用方法总结(支持win10)
  11. 代码对齐--string|stream
  12. SQL insert
  13. 双重ScrollView,RecyclerView联动实例
  14. linux mysql 5.7.25 安裝
  15. IOS - 执行时 (经常使用函数)
  16. 【JVM.12】线程安全与锁优化
  17. Spring AOP 入门实例详解
  18. 20170731 培训Bootstrap
  19. 交叉编译git
  20. iOS 屏幕录制功能

热门文章

  1. 电位器控制两个 LED 灯交替闪烁
  2. Java之Lambda表达式
  3. Ubuntu18.04 设置开机进入命令行模式
  4. IT兄弟连 HTML5教程 HTML5文字版面和编辑标签 小结及试题
  5. fjnu2019第二次友谊赛 B题
  6. TypeScript `this` 入参
  7. css盒子布局,浮动布局以及显影与简单的动画
  8. Servlet小结(面试)
  9. SQL Server有意思的数据类型隐式转换问题
  10. android binder 进程间通信机制4-Service Manager