说说你对二分查找的理解?如何实现?应用场景?

这篇具有很好参考价值的文章主要介绍了说说你对二分查找的理解?如何实现?应用场景?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 文章来源地址https://www.toymoban.com/news/detail-857918.html

说说你对二分查找的理解?如何实现?应用场景?

一、是什么

在计算机科学中,二分查找算法,也称折半搜索算法,是一种在有序数组中查找某一特定元素的搜索算法

想要应用二分查找法,则这一堆数应有如下特性:

  • 存储在数组中
  • 有序排序

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

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

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

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

如下图所示:

 

说说你对二分查找的理解?如何实现?应用场景?

 相比普通的顺序查找,除了数据量很少的情况下,二分查找会比顺序查找更快,区别如下所示:

说说你对二分查找的理解?如何实现?应用场景?

二、如何实现

基于二分查找的实现,如果数据是有序的,并且不存在重复项,实现代码如下:

function BinarySearch(arr, target) {
    if (arr.length <= 1) return -1
    // 低位下标
    let lowIndex = 0
    // 高位下标
    let highIndex = arr.length - 1

    while (lowIndex <= highIndex) {
        // 中间下标
        const midIndex = Math.floor((lowIndex + highIndex) / 2)
        if (target < arr[midIndex]) {
            highIndex = midIndex - 1
        } else if (target > arr[midIndex]) {
            lowIndex = midIndex + 1
        } else {
            // target === arr[midIndex]
            return midIndex
        }
    }
    return -1
}

如果数组中存在重复项,而我们需要找出第一个制定的值,实现则如下:

function BinarySearchFirst(arr, target) {
    if (arr.length <= 1) return -1
    // 低位下标
    let lowIndex = 0
    // 高位下标
    let highIndex = arr.length - 1

    while (lowIndex <= highIndex) {
        // 中间下标
        const midIndex = Math.floor((lowIndex + highIndex) / 2)
        if (target < arr[midIndex]) {
            highIndex = midIndex - 1
        } else if (target > arr[midIndex]) {
            lowIndex = midIndex + 1
        } else {
            // 当 target 与 arr[midIndex] 相等的时候,如果 midIndex 为0或者前一个数比 target 小那么就找到了第一个等于给定值的元素,直接返回
            if (midIndex === 0 || arr[midIndex - 1] < target) return midIndex
            // 否则高位下标为中间下标减1,继续查找
            highIndex = midIndex - 1
        }
    }
    return -1
}

实际上,除了有序的数组可以使用,还有一种特殊的数组可以应用,那就是轮转后的有序数组

有序数组即一个有序数字以某一个数为轴,将其之前的所有数都轮转到数组的末尾所得

例如,[4, 5, 6, 7, 0, 1, 2]就是一个轮转后的有序数组

该数组的特性是存在一个分界点用来分界两个有序数组,如下:

说说你对二分查找的理解?如何实现?应用场景?

分界点有如下特性:

  • 分界点元素 >= 第一个元素
  • 分界点元素 < 第一个元素

代码实现如下:

function search (nums, target) {
  // 如果为空或者是空数组的情况
  if (nums == null || !nums.length) {
    return -1;
  }
  // 搜索区间是前闭后闭
  let begin = 0,
    end = nums.length - 1;
  while (begin <= end) {
    // 下面这样写是考虑大数情况下避免溢出
    let mid = begin + ((end - begin) >> 1);
    if (nums[mid] == target) {
      return mid;
    }
    // 如果左边是有序的
    if (nums[begin] <= nums[mid]) {
      //同时target在[ nums[begin],nums[mid] ]中,那么就在这段有序区间查找
      if (nums[begin] <= target && target <= nums[mid]) {
        end = mid - 1;
      } else {
        //否则去反方向查找
        begin = mid + 1;
      }
      //如果右侧是有序的
    } else {
      //同时target在[ nums[mid],nums[end] ]中,那么就在这段有序区间查找
      if (nums[mid] <= target && target <= nums[end]) {
        begin = mid + 1;
      } else {
        end = mid - 1;
      }
    }
  }
  return -1;
};

对比普通的二分查找法,为了确定目标数会落在二分后的哪个部分,我们需要更多的判定条件

三、应用场景

二分查找法的O(logn)让它成为十分高效的算法。不过它的缺陷却也是比较明显,就在它的限定之上:

  • 有序:我们很难保证我们的数组都是有序的
  • 数组:数组读取效率是O(1),可是它的插入和删除某个元素的效率却是O(n),并且数组的存储是需要连续的内存空间,不适合大数据的情况

关于二分查找的应用场景,主要如下:

  • 不适合数据量太小的数列;数列太小,直接顺序遍历说不定更快,也更简单
  • 每次元素与元素的比较是比较耗时的,这个比较操作耗时占整个遍历算法时间的大部分,那么使用二分查找就能有效减少元素比较的次数
  • 不适合数据量太大的数列,二分查找作用的数据结构是顺序表,也就是数组,数组是需要连续的内存空间的,系统并不一定有这么大的连续内存空间可以使用

参考文献

  • https://zh.wikipedia.org/wiki/%E4%BA%8C%E5%88%86%E6%90%9C%E5%B0%8B%E6%BC%94%E7%AE%97%E6%B3%95#javascript_%E7%89%88%E6%9C%AC
  • https://www.cnblogs.com/ider/archive/2012/04/01/binary_search.html

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 说说你对二分查找的理解?如何实现?应用场景?

 

到了这里,关于说说你对二分查找的理解?如何实现?应用场景?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 说说你对贪心算法、回溯算法的理解?应用场景?

    贪心算法,又称贪婪算法,是算法设计中的一种思想 其期待每一个阶段都是局部最优的选择,从而达到全局最优,但是结果并不一定是最优的 举个零钱兑换的例子,如果你有1元、2元、5元的钱币数张,用于兑换一定的金额,但是要求兑换的钱币张数最少 如果现在你要兑换

    2024年04月28日
    浏览(47)
  • 说说你对vue的mixin的理解,有什么应用场景?

    Mixin 是面向对象程序设计语言中的类,提供了方法的实现。其他类可以访问 mixin 类的方法而不必成为其子类 Mixin 类通常作为功能模块使用,在需要该功能时“混入”,有利于代码复用又避免了多继承的复杂 先来看一下官方定义 mixin (混入),提供了一种非常灵活的方式,来

    2024年03月09日
    浏览(60)
  • 说说你对slot的理解?slot使用场景有哪些?

    定义 在Vue.js中,slot(插槽)是一种用于组件之间内容分发的机制。它允许你在父组件中编写子组件的内容,从而增加了组件的灵活性和可重用性。 Slot 艺名插槽,花名“占坑”,我们可以理解为 slot 在组件模板中占好了位置,当使用该组件标签时候,组件标签里面的内容就

    2024年02月07日
    浏览(45)
  • 说说你对算法中时间复杂度,空间复杂度的理解?如何计算?

    算法(Algorithm)是指用来操作数据、解决程序问题的一组方法。对于同一个问题,使用不同的算法,也许最终得到的结果是一样的,但在过程中消耗的资源和时间却会有很大的区别 衡量不同算法之间的优劣主要是通过时间和空间两个维度去考量: 时间维度:是指执行当前算

    2024年04月09日
    浏览(41)
  • 说说对WebSocket的理解?应用场景?

    WebSocket,是一种网络传输协议,位于 OSI 模型的应用层。可在单个 TCP 连接上进行全双工通信,能更好的节省服务器资源和带宽并达到实时通迅 客户端和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输 从上图可见, websocket 服务器与客户

    2024年04月08日
    浏览(38)
  • 你对SPA单页面的理解,它的优缺点分别是什么?如何实现SPA应用呢?

    SPA(single-page application),翻译过来就是单页应用SPA是一种网络应用程序或网站的模型,它通过动态重写当前页面来与用户交互,这种方法避免了页面之间切换打断用户体验在单页应用中,所有必要的代码(HTML、JavaScript和CSS)都通过单个页面的加载而检索,或者根据需要(通

    2024年02月10日
    浏览(49)
  • 说说你对图的理解?相关操作有哪些?

    在计算机科学中,图是一种抽象的数据类型,在图中的数据元素通常称为结点, V 是所有顶点的集合, E 是所有边的集合 如果两个顶点 v , w ,只能由 v 向 w ,而不能由 w 向 v ,那么我们就把这种情况叫做一个从  v  到  w  的有向边。 v 也被称做初始点, w 也被称为终点。这

    2024年04月22日
    浏览(48)
  • 说说你对树的理解?相关的操作有哪些?

    在计算机领域,树形数据结构是一类重要的非线性数据结构,可以表示数据之间一对多的关系。以树与二叉树最为常用,直观看来,树是以分支关系定义的层次结构 二叉树满足以下两个条件: 本身是有序树 树中包含的各个结点的不能超过 2,即只能是 0、1 或者 2 如下图,左

    2024年04月17日
    浏览(50)
  • 说说你对数据结构的理解?有哪些?区别?

    数据结构是计算机存储、组织数据的方式,是指相互之间存在一种或多种特定关系的数据元素的集合 前面讲到,一个程序 = 算法 + 数据结构,数据结构是实现算法的基础,选择合适的数据结构可以带来更高的运行或者存储效率 数据元素相互之间的关系称为结构,根据数据元

    2024年04月10日
    浏览(38)
  • 说说你对集合的理解?常见的操作有哪些?

    集合(Set),指具有某种特定性质的事物的总体,里面的每一项内容称作元素 在数学中,我们经常会遇到集合的概念: 有限集合:例如一个班集所有的同学构成的集合 无限集合:例如全体自然数集合 在计算机中集合道理也基本一致,具有三大特性: 确定性:于一个给定的

    2024年04月16日
    浏览(70)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包