明确循环不变量:变量的值可能在变化,但是它的含义是不变的

  • https://baike.baidu.com/item/循环不变量/8353186?fr=aladdin

如何写出正确的程序?

  • 明确变量的含义
  • 循环不变量
  • 小数据量调试
  • 大数据量测试


1 非递归的二分查找算法

// 二分查找法,在有序数组arr中,查找target
// 如果找到target,返回相应的索引index
// 如果没有找到target,返回-1
public static int binarySearch(Comparable[] arr, Comparable target) {// 在[l...r]的范围里寻找targetint l = 0, r = arr.length - 1;while (l <= r) {    // 当 l == r时,区间[l...r]依然是有效的//int mid = (l + r)/2;// 防止极端情况下的整形溢出,使用下面的逻辑求出midint mid = l + (r - l) / 2;if (arr[mid].compareTo(target) == 0) {return mid;}if (target.compareTo(arr[mid]) > 0) {// target在[mid+1...r]中; [l...mid]一定没有targetl = mid + 1;} else {// target < arr[mid]// target在[l...mid-1]中; [mid...r]一定没有targetr = mid - 1;}}return -1;
}

修改循环不变量

public static int binarySearch(Comparable[] arr, Comparable target) {// 在[l...r)的范围里寻找targetint l = 0, r = arr.length;// 当 l == r 时, 区间[l...r)是一个无效区间while (l < r) {int mid = l + (r - l) / 2;if (arr[mid].compareTo(target) == 0) {return mid;}if (target.compareTo(arr[mid]) > 0) {// target在[mid+1...r)中; [l...mid]一定没有targetl = mid + 1;} else {// target < arr[mid]// target在[l...mid)中; [mid...r)一定没有targetr = mid;}}return -1;
}

2 使用递归地方式实现二分查找法

  • 递归实现通常思维起来更容易
  • 递归在性能上会略差
private static int binarySearch(Comparable[] arr, int l, int r, Comparable target) {if (l > r) {return -1;}int mid = l + (r - l) / 2;if (arr[mid].compareTo(target) == 0) {return mid;} else if (arr[mid].compareTo(target) > 0) {return binarySearch(arr, l, mid - 1, target);} else {return binarySearch(arr, mid + 1, r, target);}
}
// 二分查找法,在有序数组arr中,查找target
// 如果找到target,返回相应的索引index
// 如果没有找到target,返回-1
public static int binarySearch(Comparable[] arr, Comparable target) {return binarySearch(arr, 0, arr.length - 1, target);
}

3 二分查找法的变种


测试是否正确

///**
// * @param n 返回数组大小
// * @return 返回一个重0到n的数组
// */
//private static Integer[] generateOrderedArray(int n) {
//    assert n > 0;
//    Integer[] arr = new Integer[n];
//    for (int i = 0; i < n; i++) {
//        arr[i] = i;
//    }
//    return arr;
//}
//public static void main(String[] args) {
//    //Binary Search test complete.
//    //Time cost: 1308 ms
//    int n = (int) Math.pow(10, 7);
//    Integer data[] = generateOrderedArray(n);
//    long startTime = System.currentTimeMillis();
//    for (int i = 0; i < n; i++) {
//        if (i != binarySearch(data, i)) {
//            throw new IllegalStateException("find i failed!");
//        }
//    }
//    long endTime = System.currentTimeMillis();
//    System.out.println("Binary Search test complete.");
//    System.out.println("Time cost: " + (endTime - startTime) + " ms");
//}

比较非递归和递归写法的二分查找的效率
非递归算法在性能上有微弱优势

//int N = 1000000;
//Integer[] arr = new Integer[N];
//for(int i = 0 ; i < N ; i ++) {
//    arr[i] = i;
//}测试非递归二分查找法
//long startTime = System.currentTimeMillis();对于我们的待查找数组[0...N)对[0...N)区间的数值使用二分查找,最终结果应该就是数字本身对[N...2*N)区间的数值使用二分查找,因为这些数字不在arr中,结果为-1
//for(int i = 0 ; i < 2*N ; i ++) {
//    int v = binarySearch(arr, i);
//    if (i < N) {
//        assert v == i;
//    } else {
//        assert v == -1;
//    }
//}
//long endTime = System.currentTimeMillis();
//System.out.println("Binary Search (Without Recursion): " + (endTime - startTime) + "ms");
-------------------------------------------------------------------------------------------------//测试递归的二分查找法
//startTime = System.currentTimeMillis();
//对于我们的待查找数组[0...N)对[0...N)区间的数值使用二分查找,最终结果应该就是数字本身对[N...2*N)区间的数值使用二分查找,因为这些数字不在arr中,结果为-1
//for(int i = 0 ; i < 2*N ; i ++) {
//    int v = binarySearch(arr, i);
//    if (i < N) {
//        assert v == i;
//    } else {
//        assert v == -1;
//    }
//}
//endTime = System.currentTimeMillis();
//System.out.println("Binary Search (With Recursion): " + (endTime - startTime) + "ms");
//}

二分查找 Binary Search相关推荐

  1. 八、二分查找(Binary Search)

    一.概述 二分查找(Binary Search,也称折半查找)--针对有序数据集合的查找算法 1.基本思想 类似分治思想,每次都通过跟区间的中间元素进行对比,将代查找的区间缩小为之前的一半,直到找到要 ...

  2. 二分查找(Binary Search)需要注意的问题,以及在数据库内核中的实现

    问题背景 今年的实习生招聘考试,我出了一道二分查找(Binary Search)的题目.题目大意如下: 给定一个升序排列的自然数数组,数组中包含重复数字,例如:[1,2,2,3,4,4,4,5,6,7 ...

  3. ABAP性能优化之使用二分查找(Binary Search)选项

    READ命令使用顺序查找数据表,这会降低处理速度.取而代之,使用binary search的附加命令,可以使用二分查找算法,可以帮助加快内表查找速度. 在使用binary search之前 必须首先将 ...

  4. SAPABAP性能优化技巧—使用二分查找(Binary Search)选项

    READ命令使用顺序查找数据表,这会降低处理速度.取而代之,使用binary search的附加命令,可以使用二分查找算法,可以帮助加快内表查找速度. 在使用binary search之前必须首先将内 ...

  5. Leetcode中几道二分查找(Binary Search)的算法题总结

    二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法.但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列.二分查找法的时间复杂度是对数级别的,O(lo ...

  6. 算法导论第2章(3) 二分查找 binary search

    二分查找(分治法). 二分查找也是一种分治法的实现,每一次查找将数据分为两个部分,问题规模都减小一半.这样查找的时间复杂度为logN.因为其实查找过程建立了一棵有N个节点的二叉树,查找次数是这棵树的高 ...

  7. #2020寒假集训#二分入门(Binary Search)代码笔记

    二分查找--Binary Search 原理就类似于下图啦(网上看到哒,忽略这个代价) 二分的时间复杂度一般是 O(logN) 的,超开心了有木有٩(๑>◡<๑)۶ 最简单来说,它可以分为 ...

  8. 数据结构与算法(八)二分搜索树(Binary Search Tree)

    本文主要包括以下内容: 二分搜索树的基本概念 二分搜索树的基本操作 1. 插入 2. 删除 3. 查询 实现二分搜索树 二分搜索树的不足 二分搜索树的基本概念 二分搜索树(英语:Binary Sear ...

  9. 二分搜索算法 (binary search)

    二分搜索算法 二分的本质并不是单调性,但是具有单调性一定可以使用二分,可以使用二分不一定具有单调性.二分的要点是"边界问题" 二分算法看似很容易实现,但是对于处理二分的边界上的细节 ...

最新文章

  1. 用 Navicat for Oracle 管理 Oracle10g/11g 数据库
  2. Doctype作用? 严格模式与混杂模式如何区分?它们有何意义
  3. 线程中消费者生产者的实例代码(使用Lock类)
  4. spring MVC - Inteceptors(拦截器)
  5. 测试工具 - Postman接口测试入门使用手册,Postman如何进行数据关联、自动更新cookies、简单编程
  6. 喜报!第四范式助推百胜中国斩获2020 IDC数字化转型重磅大奖
  7. VB6实现的自动停靠窗体
  8. Java编程基础03——进制运算数据类型变量
  9. 积分运算电路的设计方法详细介绍
  10. python爬取拉钩网招聘信息
  11. PHP 手机号码运营商判断2022年最新号段
  12. 黑客丛林之旅通关攻略(共14关)
  13. 人工智能知识全面讲解:生成对抗网络的应用
  14. 【转载】linux top命令及参数详解
  15. c语言赋值符号,运算符赋值运算符 - C语言教程
  16. c语言 循环语句中的终止命令,Shell break和continue命令
  17. 我在美国与“狼”共舞的日子(6)
  18. CSDN通过哪些方法获取积分
  19. TCP实战案例之即时通信、BS架构模拟
  20. 彻底解决让用户清一下浏览器缓存

热门文章

  1. 微信小程序电影购票+后台管理系统
  2. 哈趣K1和哈趣H1哪个性价比更高?谁更值得入手?
  3. 机器学习比赛、项目之模板
  4. 矩阵理论| 基础:Jordan标准型(从Jordan标准型求代数重数/几何重数/特征向量)
  5. POJ - 1077 Eight(A∗算法)
  6. c语言怎么实现plc的自锁功能,【图】plc梯形图自锁与互锁功能编程实例
  7. 总线与接口(内部总线、系统总线、外部总线)
  8. 坚持自己的初心,不做工作的奴隶
  9. LSM树——Log-Structured Merge-Tree数据结构、LSM树设计思想、LSM的数据写入操作、LSM的数据查询操作
  10. 2022登高架设考试模拟100题模拟考试平台操作