Python实现二分法查找及优化的示例详解

 更新时间:2023年04月20日 10:37:50   作者:Python 集中营  
二分查找法(Binary Search)是一种在有序数组中查找某一特定元素的算法,在本文中,我们将使用 Python 实现二分查找算法,并深入探讨算法的原理和实现细节,感兴趣的可以了解一下

二分查找法(Binary Search)是一种在有序数组中查找某一特定元素的算法,它的思想是将数组从中间分成两部分,判断目标元素在哪一部分中,然后继续在相应的部分中进行查找,直到找到目标元素或者确定目标元素不存在为止。

在本文中,我们将使用 Python 实现二分查找算法,并深入探讨算法的原理和实现细节。

1.二分查找的原理

二分查找法适用于有序数组中查找某一特定元素的场景,它的原理是将有序数组分成两个部分,每次取中间位置的元素与目标元素进行比较,根据比较结果确定要查找的元素在左边部分还是右边部分,然后继续在相应的部分中进行查找。

这样每次都能将待查找区间缩小一半,直到找到目标元素或者确定目标元素不存在为止。

二分查找法的时间复杂度为 O(log n),其中 n 表示数组的长度。这是因为每次查找都将查找区间缩小一半,最坏情况下需要查找 log n 次。

2.二分查找的实现

接下来,我们将使用 Python 实现二分查找算法。首先,我们定义一个函数binary_search,接收两个参数:一个有序数组 arr 和一个目标元素 target。

函数返回目标元素在数组中的下标,如果不存在则返回 -1。

def binary_search(arr, target):
    left = 0
    right = len(arr) - 1
    while left <= right:
        mid = (left + right) // 2
        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    return -1

在这个函数中,我们定义了两个指针 left 和 right,分别指向数组的第一个元素和最后一个元素。

然后,我们进入一个循环,直到 left > right 为止。在每次循环中,我们计算中间位置的下标 mid,并将 arr[mid] 与 target 进行比较。

如果 arr[mid] 等于 target,说明我们已经找到了目标元素,直接返回 mid。如果 arr[mid] 小于 target,说明目标元素在右边部分,我们将 left 指针移到 mid 的右边一位。

如果 arr[mid] 大于 target,说明目标元素在左边部分,我们将 right 指针移到 mid 的左边一位。这样不断缩小查找区间,直到找到目标元素或者确定目标元素不存在为止。下面是一个使用例子:

arr = [1, 3, 5, 7, 9]
target = 7
result = binary_search(arr, target)
if result == -1:
    print("Element is not present in array")
else:
    print("Element is present at index", result)

在这个例子中,我们定义了一个有序数组 arr 和一个目标元素 target,并调用了 binary_search 函数。

如果目标元素存在于数组中,函数将返回目标元素在数组中的下标;否则返回 -1。

在这个例子中,目标元素 7 存在于数组中,函数将输出 “Element is present at index 3”。

3.二分查找的优化

虽然二分查找法的时间复杂度为 O(log n),但是在实际应用中,我们可以通过一些优化来进一步提高算法的效率。

(1)查找区间的左右边界

在二分查找法中,我们需要定义一个查找区间,通常用 left 和 right 两个指针来表示。

在每次循环中,我们需要判断 left 和 right 是否重合,如果重合则说明查找区间为空,目标元素不存在于数组中。

这个判断过程需要进行多次,可以通过在循环条件中直接判断 left 和 right 是否相邻来减少判断次数,如下所示:

while left < right:
    mid = (left + right) // 2
    if arr[mid] == target:
        return mid
    elif arr[mid] < target:
        left = mid + 1
    else:
        right = mid - 1
if arr[left] == target:
    return left
else:
    return -1

在这个优化中,我们将循环条件改为 left < right,这样每次循环结束后,left 和 right 最多相差 1。

在循环结束后,我们需要判断 left 和 right 是否指向目标元素。如果 arr[left] 等于 target,则说明目标元素存在于数组中,返回 left;否则返回 -1。

(2)位运算代替除法运算

在计算中间位置的下标 mid 时,我们通常使用除法运算符 //。然而,除法运算符比位运算符效率低得多,因此我们可以使用位运算符 >> 来代替除法运算符 //,如下所示:

mid = (left + right) >> 1

在这个优化中,我们将除以 2 改为右移 1 位,即将二进制数向右移动一位,相当于除以 2。这样可以减少计算中间位置的下标所需的时间。

(3)使用 bisect 库

Python 中的 bisect 库提供了一些实用的函数,可以帮助我们更方便地进行二分查找。

其中,bisect_left 函数和 bisect_right 函数分别用于在有序数组中查找某一元素的插入位置。

这两个函数的区别在于,当有多个相同的元素时,bisect_left 函数返回第一个位置,而 bisect_right 函数返回最后一个位置。

下面是一个使用 bisect 库进行二分查找的例子:

import bisect
arr = [1, 3, 5, 7, 9]
target = 7
index = bisect.bisect_left(arr, target)
if index < len(arr) and arr[index] == target:
    print("Element is present at index", index)
else:
    print("Element is not present in array")

在这个例子中,我们使用 bisect.bisect_left 函数在有序数组 arr 中查找目标元素 target 的插入位置。

如果插入位置小于数组长度,并且插入位置处的元素等于目标元素,则说明目标元素存在于数组中,输出其下标;否则输出 “Element is not present in array”。

4.总结

二分查找法是一种高效的查找算法,适用于有序数组中查找某一特定元素的场景。通过将数组从中间分成两部分,每次取中间位置的元素与目标元素进行比较,可以将待查找区间缩小一半,从而降低查找的时间复杂度。

在实现二分查找算法时,我们需要定义一个查找区间,通常用 left 和 right 两个指针来表示。在每次循环中,我们计算中间位置的下标 mid,并将 arr[mid] 与 target 进行比较。如果 arr[mid] 等于 target,说明我们已经找到了目标元素,直接返回 mid。

如果 arr[mid] 小于 target,说明目标元素在右边部分,我们将 left 指针移到 mid 的右边一位。如果 arr[mid] 大于 target,说明目标元素在左边部分,我们将 right 指针移到 mid 的左边一位。这样不断缩小查找区间,直到找到目标元素或者确定目标元素不存在为止。

在实际应用中,我们可以通过一些优化来进一步提高算法的效率。例如,可以在循环条件中直接判断 left 和 right 是否相邻来减少判断次数;可以使用位运算符 >> 来代替除法运算符 //,减少计算中间位置的下标所需的时间;可以使用 bisect 库提供的函数来进行二分查找,更方便地实现算法。

到此这篇关于Python实现二分法查找及优化的示例详解的文章就介绍到这了,更多相关Python二分法查找内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • pycharm 激活码及使用方式的详细教程

    pycharm 激活码及使用方式的详细教程

    这篇文章主要介绍了pycharm 激活码及使用方式,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05
  • python实现守护进程、守护线程、守护非守护并行

    python实现守护进程、守护线程、守护非守护并行

    本篇文章主要介绍了python实现守护进程、守护线程、守护非守护并行,详细的介绍了守护子进程、非守护子进程并存,守护子线程非守护子进程并存的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-05-05
  • Python实现为PDF大文件批量去除水印

    Python实现为PDF大文件批量去除水印

    在阅读过程中如果遇到一些带有水印的资料是比较烦心的,而市面上去水印的功能有多要收费且很不方便,那么,如何通过Python来对这类图片水印进行去除呢,本文就来和大家分享一下实现方法吧
    2023-05-05
  • 在Python中移动目录结构的方法

    在Python中移动目录结构的方法

    这篇文章主要介绍了在Python中移动目录结构的方法,需要的朋友可以参考下
    2016-01-01
  • Python  Flask框架操作数据库的方法

    Python  Flask框架操作数据库的方法

    Flask中最方便用的数据库框架是flask_sqlalchamy,是对 SQLAlchamy 在 Flask 中的扩展,它主要在于简化Flask 中 sqlalchamy的使用,本篇文章给大家介绍Python  Flask的数据库操作使用方法,感兴趣的朋友一起看看吧
    2024-02-02
  • Python实现JS解密并爬取某音漫客网站

    Python实现JS解密并爬取某音漫客网站

    这篇文章主要介绍了Python实现JS解密并爬取某音漫客网站,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • Python Matplotlib绘图基础知识代码解析

    Python Matplotlib绘图基础知识代码解析

    这篇文章主要介绍了Python Matplotlib绘图基础知识代码解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • Python中Merge使用的示例详解

    Python中Merge使用的示例详解

    Python里的merger函数是数据分析工作中最常见的函数之一,类似于MySQL中的join函数和Excel中的vlookup函数。本文将通过一些简单的实力和大家聊聊Merge的使用,需要的可以了解一下
    2023-02-02
  • pyecharts实现数据可视化

    pyecharts实现数据可视化

    这篇文章主要介绍了pyecharts实现数据可视化,pyecharts 是百度开源的,适用于数据可视化的工具,配置灵活,展示图表相对美观,顺滑,下面更多详细内容,需要的小伙伴可以参考一下
    2022-03-03
  • python自动脚本的pyautogui入门学习

    python自动脚本的pyautogui入门学习

    这篇文章主要介绍了python自动脚本的pyautogui入门学习,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-04-04

最新评论