【问题标题】:Binary Search Implementation Using Slicing使用切片的二进制搜索实现
【发布时间】:2021-02-17 18:01:22
【问题描述】:

关于下面给出的二分查找实现:

def bin_search(arr, key):
    n = len(arr)
    if n < 2:
       return (0 if (n == 1 and arr[0] == key) else None)
    m = int(0.5 * n)
    if arr[m] > key:
       return bin_search(arr[:m], key)
    result = bin_search(arr[m:], key)
    return (result + m if result != None else None)  

对于上面的二分查找实现,时间复杂度会受到影响,因为我们正在获取数组的切片和空间复杂度,因为 Python 中的列表切片会创建一个新的列表对象。为了改进上述实现,我正在考虑引入下限和上限变量,就像在其原始实现中一样。但它会完全修改上面的代码实现。

您能否告诉我如何修改上述实现,以提高它的时间和空间复杂度,我对其复杂度的理解是否正确?

【问题讨论】:

  • 您应该只将原始数组传递给递归函数,以及搜索的高/低边界。避免生成所有这些切片。
  • @RufusVS 我也尝试过这样做。但它会完全修改现有的实现,并提供一个全新的实现。

标签: python algorithm time-complexity binary-search


【解决方案1】:

这里是迭代解,时间复杂度为O(log(n)),空间复杂度为O(1)。无需修改数组,您只需修改指针的位置。我的意思是left/right 指针。

def binary_search(array, target):
    return binary_search_helper(array, target, 0, len(array) - 1)


def binary_search_helper(array, target, left, right):
    while left <= right:
        middle = (left + right) // 2
        match = array[middle]

        if target == match:
            return middle
        elif target < match:
            right = middle - 1
        else:
            left = middle + 1

    return -1

递归解决方案:我看不到通过轻微更改来提高复杂性的方法,因为您需要使用位置而不是数组本身。这将影响您的基本案例和函数调用。这是我将空间复杂度从O(n) 降低到O(log(n)) 的尝试。

def bin_search(arr, key, left=0, right=len(arr) - 1):
    # Should change base case since we modify only pointers
    if left > right:
        return None

    # since we are not modifying our array working with length will not work
    m = int(0.5 * (left + right))

    if arr[m] == key:
        return m
    elif arr[m] > key:
       return bin_search(arr, key, left, m - 1)
    else:
        return bin_search(arr, key, m + 1, right)

PS:由于我们在函数定义中定义了right=len(arr) - 1,因此需要预先创建arr或创建另一个调用函数。我建议使用这样的调用函数:

def binary_search_caller(arr, key):
    return bin_search(arr, key, 0, len(array) - 1)

并将函数定义更改为:

def bin_search(arr, key, left, right):
    ...

【讨论】:

  • 谢谢,但是对于问题中提到的实现,我们如何稍微修改它以提高复杂性?
  • 谢谢。它有帮助
  • @tendo 唯一受到影响的是空间复杂性,因为您在每个递归函数调用中都创建了额外的空间。时间复杂度将保持不变。
  • 在实现递归解决方案时,空间复杂度可能为 O(log(n)),具体取决于内存在递归调用堆栈中的使用方式,并且取决于选择的语言。这就是为什么建议使用迭代解决方案而不是递归解决方案的原因。但通常我们说它是 O(1),因为我们没有在变量或其他东西中存储任何东西。
  • 感谢详细解释
猜你喜欢
  • 1970-01-01
  • 2017-03-28
  • 1970-01-01
  • 2013-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-24
  • 1970-01-01
相关资源
最近更新 更多