Skip to content

Commit f02d6c2

Browse files
committed
使用最小堆求topk
1 parent 2570b34 commit f02d6c2

File tree

2 files changed

+55
-2
lines changed

2 files changed

+55
-2
lines changed

docs/13_高级排序算法/quick_sort.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,7 @@ T(n) = 2T(n/2) + n
101101
- 请你补充 quicksort_inplace 的单元测试
102102
- 最坏的情况下快排的时间复杂度是多少?什么时候会发生这种情况?
103103
- 我们实现的快排是稳定的啵?
104-
- 选择基准值如果选不好就可能导致复杂度升高,算导中提到了一种『median of 3』策略,就是说选择 pivot 的时候
105-
从子数组中随机选三个元素,再取它的中位数,你能实现这个想法吗?这里我们的代码很简单地取了第一个元素作为 pivot
104+
- 选择基准值如果选不好就可能导致复杂度升高,算导中提到了一种『median of 3』策略,就是说选择 pivot 的时候 从子数组中随机选三个元素,再取它的中位数,你能实现这个想法吗?这里我们的代码很简单地取了第一个元素作为 pivot
106105
- 利用快排中的 partition 操作,我们还能实现另一个算法,nth_element,快速查找一个无序数组中的第 n 大元素,请你尝试实现它并编写单测。其实这个函数是 C++ STL 中的一个函数。
107106
- 你知道 Python 内置的 sorted 如何实现的吗?请你 Google 相关资料了解下。很多内置的排序都使用了快排的改良版。
108107

docs/15_堆与堆排序/heap_and_heapsort.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,60 @@ def test_heapsort_reverse():
125125
python 其实自带了 heapq 模块,用来实现堆的相关操作,原理是类似的。请你阅读相关文档并使用内置的 heapq 模块完成堆排序。
126126
一般我们刷题或者写业务代码的时候,使用这个内置的 heapq 模块就够用了。
127127

128+
129+
# Top K 问题
130+
面试题中有这样一类问题,让求出大量数据中的top k 个元素,比如一亿个数字中最大的100个数字。
131+
对于这种问题有很多种解法,比如直接排序、mapreduce、trie 树、分治法等,当然如果内存够用直接排序是最简单的。
132+
如果内存不够用呢? 这里我们提一下使用固定大小的堆来解决这个问题的方式。
133+
其实思路比较简单,先迭代前 k 个元素建立一个最小堆,之后的元素如果小于堆顶最小值,跳过,否则替换堆顶元素。
134+
135+
```py
136+
import heapq
137+
138+
139+
class TopK:
140+
"""获取大量元素 topk 大个元素,固定内存
141+
思路:
142+
1. 先放入元素前 k 个建立一个最小堆
143+
2. 迭代剩余元素:
144+
如果当前元素小于堆顶元素,跳过该元素(肯定不是前 k 大)
145+
否则替换堆顶元素为当前元素,并重新调整堆
146+
"""
147+
148+
def __init__(self, iterable, k):
149+
self.minheap = []
150+
self.capacity = k
151+
self.iterable = iterable
152+
153+
def push(self, val):
154+
if len(self.minheap) >= self.capacity:
155+
min_val = self.minheap[0]
156+
if val < min_val: # 当然你可以直接 if val > min_val操作,这里我只是显示指出跳过这个元素
157+
pass
158+
else:
159+
heapq.heapreplace(self.minheap, val)
160+
else:
161+
heapq.heappush(self.minheap, val)
162+
163+
def get_topk(self):
164+
for val in self.iterable:
165+
self.push(val)
166+
return self.minheap
167+
168+
169+
def test():
170+
import random
171+
i = list(range(1000))
172+
random.shuffle(i)
173+
_ = TopK(i, 10)
174+
print(_.get_topk())
175+
176+
177+
if __name__ == '__main__':
178+
test()
179+
```
180+
181+
128182
# 练习题
129183

130184
- 这里我用最大堆实现了一个 heapsort_reverse 函数,请你实现一个正序排序的函数。似乎不止一种方式

0 commit comments

Comments
 (0)