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


    本篇主要是<<数据结构和算法-王争>>教程笔记和python实现

    原理: 在一个有序数组中, 不断比较中间位置的数和目标数的大小, 如果中间位置数比目标数大, 则再用同样办法比较前半部分, 否则比较后半部分. 如果没有找到目标数的位置, 返回None, 否则返回该数的位置. 因为是不断把数组分为一半一半的找, 所以时间复杂度是O(logn).

    时间复杂度: O(logn)

    实现

    注: 要注意边界情况

    # coding:utf-8
    
    def binary_search(nums, value):
        low = 0
        high = len(nums) - 1
        # 注意是 <=
        while low <= high:
            mid = int((low + high) / 2)
            mid_value = nums[mid]
            # 注意 low 和 high 的取值, 防止发生死循环. 比如low=3, high=3
            if mid_value < value:
                low = mid + 1
            elif mid_value > value:
                high = mid - 1
            else:
                return mid
        return -1
    
    
    if __name__ == "__main__":
        nums = [1, 2, 3, 4, 5]
        print(binary_search(nums, 5))
    
    

    注意点:

    • 边界情况, 特别注意注释内容, 防止发生死循环
    • mid = int((low + high) / 2)可能发生整数溢出, 可以优化改为
    mid = low + int((high-low)/2)
    # 或
    low + int((high - low) >> 1)   # 位运算
    

    缺点:

    • 依赖数组, 不能是链表
      数据量太大不适合. 因为依赖数组, 所以必须要求内存是连续的, 比如需要连续的1G空间. 现在有2G不连续的内存也没有办法使用
    • 数组必须有序
      如果数组经常插入/删除, 每次都需要排序, 则不适合二分查找

    二分查找变形问题

    一般情况下能用二分查找解决的问题也可以使用二叉查找树和散列表来解决, 但是二分查找适合以下问题

    以下情况允许出现重复元素

    1. 查找第一个值 = 给定值的元素

    # coding:utf-8
    
    """
    查找数组中第一个=给定值的元素, 返回索引位置
    """
    
    
    def binary_search(nums, value):
        low = 0
        high = len(nums) - 1
        while low <= high:
            mid = low + ((high - low) >> 1)
            mid_value = nums[mid]
            if mid_value < value:
                low = mid + 1
            elif mid_value > value:
                high = mid - 1
            else:
                if mid == 0 or nums[mid - 1] != value:
                    return mid
                else:
                    high = mid - 1
    
        return -1
    
    
    if __name__ == "__main__":
        nums = [1, 3, 4, 5, 6, 8, 8, 8, 11, 18]
        print(binary_search(nums, 8))
    
    

    2. 查找最后一个值 = 给定值的元素

    def binary_search_2(nums, value):
        """
        查找数组中最后一个等于给定值的元素, 返回索引位置
        """
        low = 0
        high = len(nums) - 1
        last_pos = high
        while low <= high:
            mid = low + ((high - low) >> 1)
            mid_value = nums[mid]
            if mid_value < value:
                low = mid + 1
            elif mid_value > value:
                high = mid - 1
            else:
                # 如果mid==最后一位, 那么是第一个元素肯定是要找的值
                if mid == last_pos or nums[mid + 1] != value:
                    return mid
                else:
                    # 要找的值肯定在mid+1和high之间
                    low = mid + 1
    
        return -1
    
    

    3. 查找第一个 >= 给定值的元素

    def binary_search_3(nums, value):
        """
        查找数组中第一个 >= 给定值的元素, 返回索引位置
        """
        low = 0
        high = len(nums) - 1
        while low <= high:
            mid = low + ((high - low) >> 1)
            mid_value = nums[mid]
    
            if mid_value >= value:
                if mid == 0 or nums[mid - 1] < value:
                    return mid
                else:
                    high = mid - 1
            else:
                low = mid + 1
    
        return -1
    

    4. 查找最后一个 <= 给定值的元素

    def binary_search_4(nums, value):
        """
        查找数组中最后一个 <= 给定值的元素, 返回索引位置
        """
        low = 0
        high = len(nums) - 1
        last_pos = high
    
        while low <= high:
            mid = low + ((high - low) >> 1)
            mid_value = nums[mid]
    
            if mid_value > value:
                high = mid - 1
            else:
                if mid == last_pos or nums[mid + 1] > value:
                    return mid
                else:
                    low = mid + 1
    
        return -1
    

    资料

    • <<数据结构和算法>> - 王争
    • <<大话数据结构>>
  • 相关阅读:
    六十三:CSRF攻击与防御之系统准备之登录与转账功能
    六十二:CSRF攻击与防御之系统准备之注册功能
    六十一:Flask.Session之flask操作session
    并发编程之多进程篇之二
    并发编程之多进程篇之一
    网络编程之文件传输实例
    网络编程基础之粘包现象与UDP协议
    网络编程基础之Socket套接字简单应用
    TCP协议的三次握手和四次挥手
    网络编程基础之Socket套接字
  • 原文地址:https://www.cnblogs.com/zlone/p/11076409.html
Copyright © 2020-2023  润新知