美文网首页
8二分查找

8二分查找

作者: 青漾 | 来源:发表于2021-07-24 23:07 被阅读0次

二分查找是一种非常简单易懂的快速查找算法,生活中到处可见。比如说,我们现在来做一个猜字游戏。我随机写一个 0 到 99 之间的数字,然后你来猜我写的是什么。猜的过程中,你每猜一次,我就会告诉你猜的大了还是小了,直到猜中为止。你来想想,如何快速猜中我写的数字呢?

假设我写的数字是 23,你可以按照下面的步骤来试一试。(如果猜测范围的数字有偶数个,中间数有两个,就选择较小的那个。)


二分思想

还是利用二分思想,每次都与区间的中间数据比对大小,缩小查找区间的范围。为了更加直观,我画了一张查找过程的图。其中,low 和 high 表示待查找区间的下标,mid 表示待查找区间的中间元素下标。

image.jpeg

看懂这两个例子,你现在对二分的思想应该掌握得妥妥的了。我这里稍微总结升华一下,二分查找针对的是一个有序的数据集合,查找思想有点类似分治思想。每次都通过跟区间的中间元素对比,将待查找的区间缩小为之前的一半,直到找到要查找的元素,或者区间被缩小为 0

O(logn) 惊人的查找速度

二分查找是一种非常高效的查找算法,高效到什么程度呢?我们来分析一下它的时间复杂度。

我们假设数据大小是 n,每次查找后数据都会缩小为原来的一半,也就是会除以 2。最坏情况下,直到查找区间被缩小为空,才停止。

查找区间

可以看出来,这是一个等比数列。其中 n/2k=1 时,k 的值就是总共缩小的次数。而每一次缩小操作只涉及两个数据的大小比较,所以,经过了 k 次区间缩小操作,时间复杂度就是 O(k)。通过 n/2k=1,我们可以求得 k=log2n,所以时间复杂度就是 O(logn)。

二分查找的递归与非递归实现

非递归实现

  int low = 0;
  int high = n - 1;
 
  while (low <= high) {
    int mid = (low + high) / 2;
    if (a[mid] == value) {
      return mid;
    } else if (a[mid] < value) {
      low = mid + 1;
    } else {
      high = mid - 1;
    }
  }
 
  return -1;

这个代码我稍微解释一下,low、high、mid 都是指数组下标,其中 low 和 high 表示当前查找的区间范围,初始 low=0, high=n-1。mid 表示 [low, high] 的中间位置。我们通过对比 a[mid] 与 value 的大小,来更新接下来要查找的区间范围,直到找到或者区间缩小为 0,就退出。如果你有一些编程基础,看懂这些应该不成问题。现在,我就着重强调一下容易出错的 3 个地方。

1. 循环退出条件

注意是 low<=high,而不是 low<high。

2.mid 的取值

实际上,mid=(low+high)/2 这种写法是有问题的。因为如果 low 和 high 比较大的话,两者之和就有可能会溢出。改进的方法是将 mid 的计算方式写成 low+(high-low)/2。更进一步,如果要将性能优化到极致的话,我们可以将这里的除以 2 操作转化成位运算 low+((high-low)>>1)二进制除2。因为相比除法运算来说,计算机处理位运算要快得多。

3.low 和 high 的更新

low=mid+1,high=mid-1。注意这里的 +1 和 -1,如果直接写成 low=mid 或者 high=mid,就可能会发生死循环。比如,当 high=3,low=3 时,如果 a[3] 不等于 value,就会导致一直循环不退出。

如果你留意我刚讲的这三点,我想一个简单的二分查找你已经可以实现了。实际上,二分查找除了用循环来实现,还可以用递归来实现,过程也非常简单。

二分查找应用场景的局限性

  • 首先,二分查找依赖的是顺序表结构,简单点说就是数组。

  • 其次,二分查找针对的是有序数据。

  • 再次,数据量太小不适合二分查找。
    二分查找的底层需要依赖数组这种数据结构,而数组为了支持随机访问的特性,要求内存空间连续,对内存的要求比较苛刻。比如,我们有 1GB 大小的数据,如果希望用数组来存储,那就需要 1GB 的连续内存空间。

四种常见的二分查找变形问题

image.png

变体一:查找第一个值等于给定值的元素

比如下面这样一个有序数组,其中,a[5],a[6],a[7] 的值都等于 8,是重复的数据。我们希望查找第一个等于 8 的数据,也就是下标是 5 的元素。

数组

相关文章

  • python二分查找算法

    文章概述 二分查找法介绍 简单查找与二分查找对比 二分查找  二分查找算法主要思想:在有序列表中查找指定元素,先从...

  • 数据结构和算法--二分查找

    二分查找 二分查找的思想 二分查找(Binary Search)算法,也叫折半查找算法。 二分查找针对的是一个有序...

  • 二分查找

    [TOC] 二分查找的基础模板 二分查找靠左的Index基础模板 二分查找靠右的Index基础模板 二分查找插入t...

  • 二分查找法

    二分查找法 二分查找法(递归)

  • 二分查找(递归、非递归)

    二分查找(递归) 二分查找(非递归)

  • 二分查找(递归、非递归)

    二分查找(递归) 二分查找(非递归)

  • 二分查找

    什么是二分查找?二分查找,也叫折半查找(Binary Search),它是一种效率较高的查找方法。二分查找的条件:...

  • 分治算法(swift二分法排序递归实现)

    二分查找 1、二分查找(Binary Search) 2、二分查找的基本思想 swift算法实现

  • 8二分查找

    二分查找是一种非常简单易懂的快速查找算法,生活中到处可见。比如说,我们现在来做一个猜字游戏。我随机写一个 0 到 ...

  • 可查找重复元素的二分查找算法

    可查找重复元素的二分查找算法 二分查找算法思想:又称为 折半查找,二分查找适合对已经排序好的数据集合进行查找。假设...

网友评论

      本文标题:8二分查找

      本文链接:https://www.haomeiwen.com/subject/hwzvmltx.html