zoukankan      html  css  js  c++  java
  • 二分查找(Python)

    寻找一个数

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

    寻找左侧边界

    搜索区间:[left, right]

    使右边界一直收敛到所找target的左侧边界之前,而结束条件是left==right+1,因此返回left的值

    left有可能大于len(nums)-1,但不会小于0

    def _find_left_bound(nums, target):
        """
        寻找target的左边界
        """
        left, right = 0, len(nums) - 1
        while left <= right:
            mid = (left + right) // 2
            if nums[mid] < target:
                left = mid + 1
            else:
                # target <= nums[mid]
                right = mid - 1
        # nums[left]以左的元素全部小于target,nums[right]以右的元素全部大于或等于target
        # 终止时 left = right + 1,易知此时left就是target的左边界
        # 由于right的最大值能取到len(nums)-1,因此left有可能超过len(nums)-1,但left不可能小于0
        # target还可能在nums中不存在
        if left < len(nums) - 1 and nums[left] == target:
            return left
        else:
            return -1
    

    实验结果:

    >> leftbound([1, 2, 2, 3, 5, 7, 9], 2)
    >> result = 1 left = 1
    
    当target不存在,left为首个比target大的值
    >> leftbound([1, 3, 5, 7, 9], 2)
    >> result = -1 left = 1
    
    当target小于数组最小值,left为0
    >> leftbound([1, 3, 5, 7, 9], 0)
    >> result = -1 left = 0
    
    当target大于数组最小值,left为len(nums)
    >> leftbound([1, 3, 5, 7, 9], 10)
    >> result = -1 left = 5
    

    寻找右侧边界

    def _find_right_bound(nums, target):
        """
        寻找target的右边界
        """
        left, right = 0, len(nums) - 1
        while left <= right:
            mid = (left + right) // 2
            if target < nums[mid]:
                right = mid - 1
            else:
                # nums[mid] <= target
                left = mid + 1
        # nums[right]以右的元素全部大于target,nums[left]以左的元素全部小于或等于target
        # 终止时 left = right + 1,易知此时right就是target的右边界
        # 由于left的最小值能取到0,因此right有可能小于0,但不可能超过len(nums)-1
        if right >= 0 and nums[right] == target:
            return right
        else:
            return -1
    

    寻找左右边界问题的本质是找到一个位置,使所有小于target的值(且仅有这些值)都在左边(找左边界),或者所有大于target的值(且仅有这些值)都在右边(找右边界)

    时间复杂度O(logn)

    相当于从一颗二叉搜索树的根走到叶子节点,二叉搜索树的高度为O(logn),因此时间复杂度为O(logn)

    空间复杂度O(1)

  • 相关阅读:
    python爬取酷狗音乐
    python爬取酷我音乐
    排列组合+逆元模板
    python爬取QQVIP音乐
    一维数组的动态和
    买卖股票的最佳时机 II
    最佳买卖股票时机含冷冻期
    买卖股票的最佳时机
    子集
    最短无序连续子数组
  • 原文地址:https://www.cnblogs.com/luozx207/p/14069121.html
Copyright © 2011-2022 走看看