找出数组第k小的元素

解法

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

迭代形式

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)

复杂度分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

颹蕭蕭

白嫖?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值