【Leetcode】215. 数组中的第K个最大元素

 

 

 方法一:

 

这个题目首先一看就有两个方法,一个是使用基于树的算法,也就是heap堆排序,经过一番奇巧淫技之后,时间复杂度是O(n*log k)。另一个就是使用数组的算法,可以选择的算法有选择排序O(n^2),快速排序O(nlogn),冒泡排序O(n^2)或者插入排序O(n^2)等等。那么本题目最快的方法就是使用一个不太寻常的heap sort,或者使用基于数组的sort。首先我们用最容易想到的,基于数组的sort,代码如下:

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        #这个题目显然可以使用heap来完成
        sort_list=sorted(nums)
        return sort_list[-k]

然后来看看结果:

 

 

 不会吧不会吧!竟然打败了97%的用户???据我所知,python的sorted函数其实使用了快速排序,那么时间复杂度是O(nlogn),那我们用时间复杂度更小的heap sort来试试看?

 方法二:

我们直接使用python当中heap的库,这样使用起来更方便一点,不然就要手撕heap了!我们将所有的元素加入进heap当中,进行排序,时间复杂度是O(nlogn)代码如下:

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        heap = []
        for num in nums:
            heapq.heappush(heap, num)
            if len(heap) > k:
                heapq.heappop(heap)
        return heap[0]

最终的运行结果如下:

 

 

 方法三:

这居然连快速排序还不如....显然不是最优的解法,我们使用第三种解法,对heap进行不同的处理,最后的时间复杂度是O(nlogk),由于Python自带的heapq模块只能够建立小顶堆,也就是min-heap,无法建立max-heap。我们速度最快的这种方法是使用的max-heap才能够达到这样的时间复杂度,而Python的heapq以及sorted底层都是用速度飞快的C语言实现的,我如果用Python手撸一个max—heap,最后可能还比不上Python自带的sorted或者heapq。尝试了一下的代码如下,使用数组实现heap:

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        heap = Heap(k + 1)
        for num in nums:
            if not heap.push(num):
                heap.pop()
                heap.push(num)
        if heap.size == k + 1:
            heap.pop()
        return heap.peek()
        
class Heap:
    def __init__(self, length):
        self.heap = [0] * (length + 1)
        self.size = 0
    
    def push(self, val):
        if self.size == len(self.heap) - 1:
            return False
        self.size += 1
        self.heap[self.size] = val
        self.shift_up(self.size)
        return True
    
    def pop(self):
        val = self.heap[1]
        self.heap[1] = self.heap[self.size]
        self.heap[self.size] = 0
        self.size -= 1
        self.shift_down(1)
        return val
    
    def peek(self):
        return self.heap[1]
    
    def shift_up(self, i):
        val = self.heap[i]
        while i >> 1 > 0:
            parent = i >> 1
            if val < self.heap[parent]:
                self.heap[i] = self.heap[parent]
                i = parent
            else:
                break
        self.heap[i] = val
    
    def shift_down(self, i):
        val = self.heap[i]
        while i << 1 <= self.size:
            child = i << 1
            if child != self.size and self.heap[child + 1] < self.heap[child]:
                child += 1
            if val > self.heap[child]:
                self.heap[i] = self.heap[child]
                i = child
            else:
                break
        self.heap[i] = val

最后时间复杂度居然只打败了百分之三十的people,还真不如直接heapq和快速排序了...

 

posted @ 2021-04-20 16:59  Geeksongs  阅读(87)  评论(2编辑  收藏  举报

Coded by Geeksongs on Linux

All rights reserved, no one is allowed to pirate or use the document for other purposes.