132优秀项目组初选评比

69 阅读1分钟

分析

这道题最简单的是排序后遍历。因为有排序,所以时间复杂度是nlognn\log n。后续的处理算法逻辑不影响算法的时间复杂度。但是如果使用二分查找可以让算法整体的实际运行时间缩短。

思路

可以用桶排序把算法的时间复杂度降到mlogmm \log m,我这里只用桶计算前缀和。

代码

def solution(m: int, n: int, a: list) -> int:
    if len(a) > 2*n:
        return -1
        
    a.sort()
    total=len(a)
    bucket=[[a[0],1]]
    for _, num in enumerate(a[1:], start=1):
        if num!=bucket[-1][0]:
            bucket.append([num, 1])
        else:
            bucket[-1][1]+=1
    prefix_sum=[0]*len(bucket)
    prefix_sum[0]=bucket[0][1]
    for i, (_, count) in enumerate(bucket[1:], start=1):
        prefix_sum[i] = prefix_sum[i-1]+count 
    idx=max(m, total-n)
    locate = binarySearch(prefix_sum, idx)
    if m<=total-prefix_sum[locate] and total-prefix_sum[locate]<=n:
        return bucket[locate][0]
    else:
        return -1
def binarySearch(a, target):
    '''
    大于等于target中最小的
    '''
    lo = 0
    hi = len(a)
    while lo<hi:
        mid = (lo+hi)//2
        if target<a[mid]:
            hi=mid 
        else:
            if lo==mid:
                break
            lo=mid 
    if a[lo]==target:
        return lo 
    else:
        return lo+1