【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和快速排序了...