數據結構和算法-二分查找

本篇主要是< <數據結構和算法-王爭> >教程筆記和python實現 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不連續的內存也沒有辦法使用
  • 數組必須有序
    若是數組常常插入/刪除, 每次都須要排序, 則不適合二分查找

二分查找變形問題

通常狀況下能用二分查找解決的問題也可使用二叉查找樹和散列表來解決, 可是二分查找適合如下問題code

如下狀況容許出現重複元素排序

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

資料

  • < <數據結構和算法> > - 王爭
  • < <大話數據結構> >

相關文章
相關標籤/搜索