Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x 关于递归二分法搜索的大O符号问题_Python 3.x_Algorithm_Recursion_Big O - Fatal编程技术网

Python 3.x 关于递归二分法搜索的大O符号问题

Python 3.x 关于递归二分法搜索的大O符号问题,python-3.x,algorithm,recursion,big-o,Python 3.x,Algorithm,Recursion,Big O,我参加了麻省理工学院举办的Python课程(2016年秋季6.0001),在他的一次讲座中,教授描述了一个函数,如果元素(e)在列表(L)中,则返回True,否则返回False: def bisect_search1(L, e): if L == []: return False elif len(L) == 1: return L[0] == e else: half = len(L)//2

我参加了麻省理工学院举办的Python课程(2016年秋季6.0001),在他的一次讲座中,教授描述了一个函数,如果元素(e)在列表(L)中,则返回
True
,否则返回
False

def bisect_search1(L, e):
    if L == []:
        return False
    
    elif len(L) == 1:
        return L[0] == e
    
    else:
        half = len(L)//2
        if L[half] > e:
            return bisect_search1(L[:half], e)
        else:
            return bisect_search1(L[half:], e)

继续看下一张幻灯片,我知道对分搜索调用的复杂性为O(logn),因为每个循环或调用的输入都要减半

从幻灯片中我仍然不明白以下几点:

  • O(n)对于复制列表的每个对分搜索调用,这是设置每个调用的成本,因此对每个递归级别执行此操作
  • 如果我们真的很小心,请注意,要复制的列表的长度在每次递归调用时也会减半,结果表明,复制的总成本是O(n),这主要是由于递归调用导致的log n成本
我仍然不明白的是:

  • 对列表的一部分进行切片和复制整个列表是否具有相同的大O复杂性O(n)
  • 如果是,我理解为什么函数有O(n logn)复杂度。但是这个“证明了复制的总成本是O(n),并且由于递归调用,这占了logn成本的主导地位,这意味着什么呢?这是否意味着函数现在具有O(n)复杂性
  • 我很抱歉,如果以前有人问过类似的问题,而且似乎是初学者

  • 获取一个列表切片的代价是O(m),其中m是切片的大小。这是因为它必须创建一个大小为m的新列表并填充其条目

  • 在第一次调用中,切片的大小为n/2。在第一个递归调用中,获取的切片大小现在为n/4。因此,获取切片的总成本为:O(n/2+n/4+n/8+…)=O(n)(通过获取几何级数之和)


  • 切片列表所需的时间与切片的长度成比例。如果您有一个大小为n的列表,并且正在将其切片一半,则时间与n/2成正比,因此为O(n)


    这位教授引用的关于复制成本占递归调用成本的主要部分的话只是说,通常二分搜索是O(logn)——递归调用的深度——但这里也有一些复制,其中一些需要O(n)时间。你可以用这些词来证明O(n logn)是一个上限,但它们不能证明精确的复杂性(实际上是O(n),因为每次复制的数量都是一半)。

    谢谢!。对于第二点,这是我的第一个想法,但是
    half
    变量使用整数除法(//),因此我不确定它是否真的是一个几何级数。@yfr整数除法引入的误差足够小,以至于它们不会改变大O。您可以使此计算更正式(更复杂)。例如,取N=比N大的2的下一次幂。然后你可以证明解是O(N/2+N/4+…)=O(N)=O(N)。谢谢你的详细解释!比方说,假设我没有将列表切成一半,而是复制了整个列表。这是否意味着O(n+n+n+…)=O(n),并且函数仍然是O(n logn)复杂度?@yfr如果在每个递归调用中执行n个步骤,其中n是原始列表大小,那么总数将是O(n logn)。但是如果执行n个步骤,其中n是传递给递归调用的列表的大小,它仍然是O(n)总计(我假设列表大小仍然以某种方式减少了一半,因为否则会有无限递归)。我想我现在更了解它了@保尔汉金的解释也让它更清楚。谢谢你们两个!