topN问题

 topN问题:给出一个数组,找出前N个最大的元素。

topN问题可以用分治法解决,这个问题与快速排序类似,快速排序是用一个数对数组进行划分,topN问题则不需完成排序,只需划分出前n个最大的数字即可。所以可以采用快排中partition函数的操作,将每次操作的返回值与N作对比,若比N小则对N及其后续的元素继续进行划分,若比N大则对N及其之前的元素进行划分,直到找出N。

该方法的时间复杂度:Θ(n)

示例代码:

import random


def partition(a,i,j):
    if i < j:
        key = random.randint(i,j)
        tmp = a[key]
        a[key] = a[j]
        a[j] = tmp
        k = i-1
        for index in range(i,j):
            if a[index] > a[j]:
                k += 1
                tmp = a[k]
                a[k] = a[index]
                a[index] = tmp
        else:
            k += 1
            tmp = a[k]
            a[k] = a[j]
            a[j] = tmp
            #此处与快排不同,当欲划分的数组元素皆相同时会导致栈溢出,所以当元素相同时
            #返回一个随机下标
            if a[i] == a[j]:
                return random.randint(i,j)
        return k
    return i
            
def find_top_n(a,i,j,top_index):
    top_ret = partition(a,i,j)
    #当返回值比top_index小时,对top_ret及后续元素继续进行划分
    if top_ret < top_index:
        return find_top_n(a,top_ret,j,top_index)
    #当返回值比top_index大时,对top_ret及先前元素继续进行划分
    elif top_ret > top_index:
        return find_top_n(a,i,top_ret,top_index)
    #当返回值等于top_index时,已找到TopN
    else:
        return top_ret


def main(args):
    a = []
    for i in range(10):
        a.append(random.randint(0,100))
    print(a)
    find_top_n(a,0,len(a)-1,5)
    print(a)
    return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))

 

posted @ 2018-11-01 20:41  东东欧尼酱  阅读(2711)  评论(1编辑  收藏  举报