在列表中找到先减小然后减小的最小值,并且可能包含重复项

时间:2018-10-15 04:40:12

标签: python list minimum

给出一个可以分为两部分的列表L [:z]和L [z:],以使第一个不增加,第二个不减少并且可以包含或不包含重复元素,请创建一个这样的功能:


输入:

  • 如上所述的列表L
  • 值k,代表列表中重复给定值的最大次数

输出:

  • 列表的最小值

复杂性和要求

  • O(log n)
  • 只能使用不包含最小/最大的内置库函数

我有以下内容:

def findmin(L, k = None):
    left = 0
    right = len(L)-1
    foundmin = False

    while not foundmin:
        mp = (left + right)//2
        if L[mp] > L[mp+1]:
            left = mp
        elif L[mp-1] < L[mp]:
            right = mp+1
        else:
            return L[mp]

它仅适用于某些列表,例如: L = [9,9,4,3,2,1,7,7,10,10]

但是它不适用于以下列表: L = [6,5,4,3,3,3,3,3,3,3,3,3,1,7,7,7,7]

我尝试修改该功能以容纳重复的元素而无济于事。我也没有看到函数的输入k的效用。有想法吗?

2 个答案:

答案 0 :(得分:2)

此代码在O(logn)中运行,并且不使用k参数。

这是一种类似于@coldspeed的二进制搜索。

def find_min(l, k=None):
    left = 0
    right = len(l) - 1
    while left <= right:
        middle = (left + right) // 2
        if l[middle] < l[left] or (l[middle] == l[left] and middle > left):
            left = middle
        elif l[middle] < l[right] or (l[middle] == l[right] and middle < right):
            right = middle
        else:
            return l[middle]

答案 1 :(得分:1)

解决方案的问题是,如果mp两侧的数字等于mp,则您的算法将输出L [mp]。因此,在第二种情况下,它输出3。一个简单的事情是检查下一个不相等的数字,而不是仅检查相邻的不相等数字。

修改后的解决方案:

def findmin(L, k = None):
    left = 0
    right = len(L)-1
    foundmin = False

    while left<right:
        print(left, right)
        mp = (left + right)//2
        next_diff = mp+1
        while(next_diff < len(L)-1 and L[next_diff] == L[mp]):
            next_diff+=1
        if L[mp] > L[next_diff]:
            left = next_diff
        elif L[mp] <= L[next_diff]:
            right = mp
    return L[left]

P.S:尽管在这种情况下,复杂度变为O(k * log n)。