提高返回列表中元素首次出现的索引的函数的时间复杂度

时间:2018-10-16 06:19:28

标签: python list binary-search

更新1(10月16日):原始代码中有一些逻辑错误已得到纠正。现在,下面的更新代码将为所有符合特殊列表标准的列表L,S.T产生正确的输出。

我正在尝试减少以下功能的运行时间:

“ firstrepeat”函数接收特殊列表L和一个索引,并产生最小索引,使得L [i] == L [j]。换句话说,无论L [i]处的元素是什么,“ firstrepeat”函数都会返回该元素在列表中首次出现的索引。


列表L有什么特别之处?:

  • 该列表可以在列表的增加侧或减少侧包含重复的元素,但不能同时包含两者。即[3,2,1,1,1,5,6]可以,但不可以[4,3,2,2,1,2,3]
  • 列表先减小(或保持不变),然后又增大(或保持不变)。

  • 示例:

    L = [4,2,0,1,3] 
    L = [3,3,3,1,0,7,8,9,9]
    L = [4,3,3,1,1,1]
    L = [1,1,1,1]
    

示例输出:

假设我们有L = [4,3,3,1,1,1]

firstrepeat(L,2)将输出1

firstrepeat(L,5)将输出3


我有以下代码。我相信复杂度是O(log n)或更好(尽管我可能会遗漏一些东西)。我正在寻找提高时间复杂度的方法。

def firstrepeat(L, i):
    left = 0
    right = i
    doubling = 1
    #A Doubling Search
    #In doubling search, we start at one index and then we look at one step 
    #forward, then two steps forward, then four steps, then 8, then 16, etc. 
    #Once we have gone too far, we do a binary search on the subset of the list 
    #between where we started and where we went to far.
    while True:
        if (right - doubling) < 0:
            left = 0
            break
        if L[i] != L[right - doubling]:
            left = right - doubling
            break
        if L[i] == L[right - doubling]:
            right = right - doubling
            doubling = doubling * 2
    #A generic Binary search
    while right - left > 1:
        median = (left + right) // 2
        if L[i] != L[median]:
            left = median
        else:
            right = median

    f L[left] == L[right]:
        return left
    else: 
        return right

0 个答案:

没有答案