Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.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 在列表中找到一个下降点。这可以在O(日志n)中完成吗?_Python_Algorithm_Recursion_Big O_Divide And Conquer - Fatal编程技术网

Python 在列表中找到一个下降点。这可以在O(日志n)中完成吗?

Python 在列表中找到一个下降点。这可以在O(日志n)中完成吗?,python,algorithm,recursion,big-o,divide-and-conquer,Python,Algorithm,Recursion,Big O,Divide And Conquer,我有一个整数列表,我试图通过使用递归算法来识别整数列表中的dip来实现O(logn)。dip是紧跟在等于或大于其本身的数字之后的任何数字,因此x>=dip由于您只对查找任何单一dip感兴趣,因此二进制搜索方法将起作用,并进行一些调整 i) 不要在每次迭代中检查中间的元素,而是检查中间的两个(相邻值) ii)比较这两个“中点”,选择较小的一个,以及与该选定值位于中点同一侧的集合的一半 iii)重复此操作,就像使用常规二进制搜索一样 iv)当您正在检查的装置降到只有一个值时,您将发现您的下倾 例如:

我有一个整数列表,我试图通过使用递归算法来识别整数列表中的dip来实现O(logn)。dip是紧跟在等于或大于其本身的数字之后的任何数字,因此x>=dip由于您只对查找任何单一dip感兴趣,因此二进制搜索方法将起作用,并进行一些调整

i) 不要在每次迭代中检查中间的元素,而是检查中间的两个(相邻值)

ii)比较这两个“中点”,选择较小的一个,以及与该选定值位于中点同一侧的集合的一半

iii)重复此操作,就像使用常规二进制搜索一样

iv)当您正在检查的装置降到只有一个值时,您将发现您的下倾

例如: 1,2,3,4,6,2,8,3,6,9,0,2

i) 中间的两个值是2和8,如上面粗体显示的

ii)2<8,因此选择2,以及设置的左半部分:

1,2,3,4,6,2

iii)重复

享受编码的乐趣!^^


注意:如果遇到相等的中点对,会有轻微的摩擦。然后需要将它们与相邻的第三个术语进行比较。如果该项也等于其他两项,则取三项中的中间一项作为倾角。否则,选择具有较小值的集合的一半,并返回到步骤(i)继续迭代。

答案为是。根据以下发现,峰值(与倾角正好相反)需要
O(对数n)
时间。但区别是肤浅的,所描述的算法可以以完全相似的方式进行调整。这是一个python版本:

def find_dip(lst):
    start, end = 0, len(lst) - 1
    while start < end:
        if end - start == 1: return start if lst[start] <= lst[end] else end
        mid = (start + end) / 2
        a, b, c = lst[mid - 1: mid + 2]
        if a >= b <= c: return mid
        if a <= b: end = mid - 1
        else: start = mid + 1
    return end
def find_dip(lst):
开始,结束=0,长度(lst)-1
开始<结束时:

如果end-start==1:return start如果lst[start]=b,那么如果您添加您编写的代码块,即使它们不满足您的性能要求,您的问题在这里也会得到更好的接受。我不确定您是否可以通过任意输入实现O(logn)时间。例如,二进制搜索只能以对数方式工作,因为您知道输入已排序。在这种情况下,线性可能是您的下限。在最坏的情况下,绝对不可能得到O(logn),因为所有元素可能都必须在某个点进行检查(因为列表没有属性,所以不先读取它们就无法获得有关其元素的信息):最坏的情况必须是O(n)。很好。关键的“窍门”是在两个端点定义“下倾”。这意味着,要么(a)至少有一个端点必须是一个dip,你可以在O(1)时间内检查,要么(b)两个端点都有一个较低的邻居,这意味着它们之间必须有一个dip——因为如果没有,这可能只意味着列表无限长。在第二种情况下,如果你在两者之间选择一个新的点进行尝试,你会发现,类似地,这是(a)一个下降;或者(b)必须至少有一个较低的邻居,在这种情况下,您可以从该“侧”重新开始。
def find_dip(lst):
    start, end = 0, len(lst) - 1
    while start < end:
        if end - start == 1: return start if lst[start] <= lst[end] else end
        mid = (start + end) / 2
        a, b, c = lst[mid - 1: mid + 2]
        if a >= b <= c: return mid
        if a <= b: end = mid - 1
        else: start = mid + 1
    return end