时间复杂度O(nlogk),空间复杂度O(1)。
用类似寻找k个最大数的思路,在原列表上维护一个长度为k的小根堆。
遍历列表a[K:],如果存在比堆里元素大的值(只要比堆顶元素(最小值)大),就换掉原堆顶,然后调整堆。
遍历完列表之后,长度为k的堆内的值均不小于外部的值,且堆顶为堆内最小值,即第k大。
class Solution:
    # 小根堆调整函数
    @staticmethod
    def heapAdjust(lis, i, end):
        j = 2*i + 1
        while j <= end:
            if j+1 <= end and lis[j+1] < lis[j]:
                j += 1
            if lis[j] < lis[i]:
                lis[j], lis[i] = lis[i], lis[j]
                i = j
                j = 2*i + 1
            else:
                break
    def findKth(self , a: List[int], n: int, K: int) -> int:
        # 逆序,把前k个元素构建成小堆
        for i in range((K-1-1)//2, -1, -1):     # 在原列表上维护一个大小为k的小堆,堆顶最小
            self.heapAdjust(a, i, K-1)
        for i in range(K, len(a)):
            if a[0] < a[i]:        # 外边元素大,纳入,调整
                a[0], a[i] = a[i], a[0]
                self.heapAdjust(a, 0, K-1)
        return a[0]                # 最后堆顶元素不小于外面元素,不大于堆里的k-1个元素,故是第k大