详解Selection Problem

本文详细解析了Selection Problem,即找出n个数中第k大的数。介绍了5种不同的解法,包括排序、堆排序和快速排序的partition策略等,以及它们的时间复杂度分析。此外,还讨论了此问题的衍生问题,如BST中的Kth largest、数据流的中位数计算等。
摘要由CSDN通过智能技术生成

1 问题描述

选择问题(Selection Problem):有n个整数,给定一个整数k,找出n个数中第k大的数。

我们可以先从以下角度进行思考:

  1. n和k的大小关系是怎么样的?
  2. n个整数的分布情况是怎么样的?

对于第1点,如果k比n大,答案显然不存在;对于第2点,如果n个整数的分布比较特殊(例如都在0到10之间),那么可能会影响到解题策略。这些情况需要事先和面试官确认。

2 不同的解法

确认好以后就可以开始做题啦!我们假定答案总是存在的,至于n个整数的分布如何影响解题策略,下面慢慢说。

2.1 算法1

算法描述:将n个数都读进一个数组,对这个数组排序,然后返回第(n-k)个位置的数。

这种做法的开销主要来自两方面:首先是需要用一个数组写入n个数,其次是排序。前者要O(n)时间;而对于后者,可以证明:任何基于比较的排序算法的最优下界是O(nlogn)(参见:https://www.geeksforgeeks.org/lower-bound-on-comparison-based-sorting-algorithms/)。所以如果使用基于比较的排序,总的时间复杂度是O(n + nlogn) = O(nlogn)。

下面给出一个具体例子,排序算法是快速排序:

def qsort(L):
    if len(L) <= 1: return L
    return qsort([lt for lt in L[1:] if lt < L[0]]) + \
           L[0:1] + \
           qsort([ge for ge in L[1:] if ge >= L[0]])

def solve(arr, k):
    return qsort(arr)[len(arr) - k]

# Test here
class TestCase:
    def __init__(self, arr, k):
        self.arr = arr
        self.k = k

def test():
    case1 = TestCase([3,1,4,1,5,9,2,6,5,3], 1)
    case2 = TestCase([1,2,3,4,5,6,7,8,9,10], 1)
    assert(solve(case1.arr, case1.k) == 9)
    assert(solve(case2.arr, case2.k) == 10)
    print("Accepted!")
    
if __name__=="__main__":
    test()

这样,算法的平均时间复杂度和最好时间复杂度是O(nlogn),但在最坏情况下是O(n^2)。关于常见排序算法的性能,可以参见下表:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值