找出数组第k小的元素

*爱你&永不变心* 提交于 2020-01-14 01:48:30

解法

  1. 首先容易想到的做 kk 次冒泡, 复杂度为 O(nk)O(nk)
  2. 或者先排序再找第 kk 个元素,复杂度为 O(nlogn)O(n\log n)
  3. 建立 kk 个元素的大根堆,遍历后续 nkn-k 个元素,如果比根小就替换根, 复杂度O(nlogk)O(n\log k)
  4. 利用分割技术 (partitioning),复杂度为 O(nlogk)O(n\log k)

迭代形式

import random

def kthSmallest(data, k):
    "Find the nth rank ordered element (the least value has rank 0)."
    data = list(data)
    if not 0 <= k < len(data):
        raise ValueError('not enough elements for the given rank')

    while True:
        pivot = random.choice(data)
        pcount = 0
        low, high = [], []
        for elem in data:
            if elem < pivot:
                low.append(elem)
            elif elem > pivot:
                high.append(elem)
            else:
                pcount += 1
        if k < len(low):
            data = low
        elif k < len(low) + pcount:
            return pivot
        else:
            data = high
            k -= len(low) + pcount

递归形式

def kthSmallest(data, k):

    if not 0 <= k < len(data):
        raise ValueError('not enough elements for the given rank')

    pivot = random.choice(data)
    pcount = 0
    low, high = [], []
    for elem in data:
        if elem < pivot:
            low.append(elem)
        elif elem > pivot:
            high.append(elem)
        else:
            pcount += 1
    if k < len(low):
        return kthSmallest(low, k)
    elif k < len(low) + pcount:
        return pivot
    else:
        return kthSmallest(high, k-len(low)-pcount)

测试

A = [i for i in range(1000)]
random.shuffle(A)
for i in range(len(A)):
    assert(kthSmallest(A, i) == i)

复杂度分析

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!