Skip to content

Commit e508168

Browse files
authored
Merge branch 'PegasusWang:master' into master
2 parents da6897b + 3469a79 commit e508168

File tree

6 files changed

+539
-20
lines changed

6 files changed

+539
-20
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,12 @@ Python 抽象程度比较高, 我们能用更少的代码来实现功能,同
121121
## 算法可视化
122122

123123
学习算法的过程中有时候会比较抽象,这里给大家推荐一些可视化的网站,方便更直观地理解各种算法和数据结构的执行步骤:
124+
遇到一个算法或数据结构,你可以 google 搜索 "名称+ visualization" 找到一些可视化网站方便理解,比如学习跳跃表的时候笔者就
125+
可以通过 goole "skip list visualization" 搜到一些可视化网站帮助你理解它的工作原理。
124126

125127
- https://github.com/algorithm-visualizer/algorithm-visualizer
126128
- https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
129+
- https://cmps-people.ok.ubc.ca/ylucet/DS/Algorithms.html
127130
- https://runestone.academy/runestone/books/published/pythonds/index.html#
128131

129132
## 讲课形式

docs/03_链表/lru_cache.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,83 @@ def test():
132132

133133
if __name__ == '__main__':
134134
test()
135+
136+
137+
######################################### 使用双链表实现 LRUcache ####################################################
138+
"""
139+
一般面试中不会让我们直接用内置结构,所以这里提供一个自己实现的双链表+map lru 缓存。这也是力扣上的一道真题:
140+
[146] LRU 缓存 https://leetcode-cn.com/problems/lru-cache/description/
141+
"""
142+
143+
class ListNode:
144+
def __init__(self, key=None, value=None):
145+
self.key = key
146+
self.value = value
147+
self.prev = self.next = None
148+
149+
150+
class List:
151+
def __init__(self):
152+
"""循环双链表。注意增加了虚拟头尾结点 head,tail 方便处理"""
153+
self.head = ListNode()
154+
self.tail = ListNode()
155+
self.head.prev = self.head.next = self.tail
156+
self.tail.next = self.tail.prev = self.head
157+
158+
def delete_node(self, node): # 删除指定节点
159+
node.prev.next = node.next
160+
node.next.prev = node.prev
161+
162+
def add_to_head(self, node): # 指定节点添加到 self.head 后
163+
nextnode = self.head.next
164+
node.next = nextnode
165+
node.prev = self.head
166+
self.head.next = node
167+
nextnode.prev = node
168+
169+
170+
class LRUCache(object):
171+
172+
def __init__(self, capacity):
173+
"""
174+
思路:循环双链表 + 字典
175+
:type capacity: int
176+
"""
177+
self.map = dict()
178+
self.ll = List()
179+
self.capacity = capacity
180+
181+
def get(self, key):
182+
"""
183+
:type key: int
184+
:rtype: int
185+
"""
186+
if key not in self.map:
187+
return -1
188+
189+
node = self.map[key]
190+
self.ll.delete_node(node)
191+
self.ll.add_to_head(node)
192+
return node.value
193+
194+
def put(self, key, value):
195+
"""
196+
:type key: int
197+
:type value: int
198+
:rtype: None
199+
"""
200+
if key in self.map: # 更新不会改变元素个数,这里不用判断是否需要剔除
201+
node = self.map[key]
202+
node.value = value # 修改结构体会也会修改 map 对应 value 的引用
203+
self.ll.delete_node(node)
204+
self.ll.add_to_head(node)
205+
else:
206+
if len(self.map) >= self.capacity: # 直接用 len(self.map) ,不需要self.size 字段了
207+
tailnode = self.ll.tail.prev
208+
self.ll.delete_node(tailnode)
209+
del self.map[tailnode.key]
210+
211+
node = ListNode(key, value)
212+
self.map[key] = node
213+
self.ll.add_to_head(node)
214+
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# python3
2+
class MinHeap:
3+
def __init__(self):
4+
"""
5+
这里提供一个最小堆实现。如果面试不让用内置的堆非让你自己实现的话,考虑用这个简版的最小堆实现。
6+
一般只需要实现 heqppop,heappush 两个操作就可以应付面试题了
7+
parent: (i-1)//2。注意这么写 int((n-1)/2), python3 (n-1)//2当n=0结果是-1而不是0
8+
left: 2*i+1
9+
right: 2*i+2
10+
参考:
11+
https://favtutor.com/blogs/heap-in-python
12+
https://runestone.academy/ns/books/published/pythonds/Trees/BinaryHeapImplementation.html
13+
https://www.askpython.com/python/examples/min-heap
14+
"""
15+
self.pq = []
16+
17+
def min_heapify(self, nums, k):
18+
"""递归调用,维持最小堆特性"""
19+
l = 2*k+1 # 左节点位置
20+
r = 2*k+2 # 右节点
21+
if l < len(nums) and nums[l] < nums[k]:
22+
smallest = l
23+
else:
24+
smallest = k
25+
if r < len(nums) and nums[r] < nums[smallest]:
26+
smallest = r
27+
if smallest != k:
28+
nums[k], nums[smallest] = nums[smallest], nums[k]
29+
self.min_heapify(nums, smallest)
30+
31+
def heappush(self, num):
32+
"""列表最后就加入一个元素,之后不断循环调用维持堆特性"""
33+
self.pq.append(num)
34+
n = len(self.pq) - 1
35+
# 注意必须加上n>0。因为 python3 (n-1)//2 当n==0 的时候结果是-1而不是0!
36+
while n > 0 and self.pq[n] < self.pq[(n-1)//2]: # parent 交换
37+
self.pq[n], self.pq[(n-1)//2] = self.pq[(n-1)//2], self.pq[n] # swap
38+
n = (n-1)//2
39+
40+
def heqppop(self): # 取 pq[0],之后和pq最后一个元素pq[-1]交换之后调用 min_heapify(0)
41+
minval = self.pq[0]
42+
last = self.pq[-1]
43+
self.pq[0] = last
44+
self.min_heapify(self.pq, 0)
45+
self.pq.pop()
46+
return minval
47+
48+
def heapify(self, nums):
49+
n = int((len(nums)//2)-1)
50+
for k in range(n, -1, -1):
51+
self.min_heapify(nums, k)
52+
53+
54+
def test_MinHeqp():
55+
import random
56+
l = list(range(1, 9))
57+
random.shuffle(l)
58+
pq = MinHeap()
59+
for num in l:
60+
pq.heappush(num)
61+
res = []
62+
for _ in range(len(l)):
63+
res.append(pq.heqppop()) # 利用 heqppop,heqppush 实现堆排序
64+
65+
def issorted(l): return all(l[i] <= l[i+1] for i in range(len(l) - 1))
66+
assert issorted(res)

0 commit comments

Comments
 (0)