Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 85145c1

Browse files
committed
added some heap problems
1 parent 2b5de17 commit 85145c1

File tree

2 files changed

+241
-0
lines changed

2 files changed

+241
-0
lines changed

‎README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
- [二叉树](./data_structure/binary_tree.md)
2727
- [链表](./data_structure/linked_list.md)
2828
- [栈和队列](./data_structure/stack_queue.md)
29+
- [优先级队列(堆)](./data_structure/heap.md)
2930
- [二进制](./data_structure/binary_op.md)
3031

3132
### 基础算法篇 🐮

‎data_structure/heap.md

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
# 优先级队列 (堆)
2+
3+
用到优先级队列 (priority queue) 或堆 (heap) 的题一般需要维护一个动态更新的池,元素会被频繁加入到池中或从池中被取走,每次取走的元素为池中优先级最高的元素 (可以简单理解为最大或者最小)。用堆来实现优先级队列是效率非常高的方法,加入或取出都只需要 O(log N) 的复杂度。
4+
5+
## Kth largest/smallest
6+
7+
### [kth-largest-element-in-a-stream](https://leetcode-cn.com/problems/kth-largest-element-in-a-stream/)
8+
9+
```Python
10+
class KthLargest:
11+
12+
def __init__(self, k: int, nums: List[int]):
13+
self.K = k
14+
self.min_heap = []
15+
for num in nums:
16+
if len(self.min_heap) < self.K:
17+
heapq.heappush(self.min_heap, num)
18+
elif num > self.min_heap[0]:
19+
heapq.heappushpop(self.min_heap, num)
20+
21+
def add(self, val: int) -> int:
22+
if len(self.min_heap) < self.K:
23+
heapq.heappush(self.min_heap, val)
24+
elif val > self.min_heap[0]:
25+
heapq.heappushpop(self.min_heap, val)
26+
27+
return self.min_heap[0]
28+
```
29+
30+
### [kth-smallest-element-in-a-sorted-matrix](https://leetcode-cn.com/problems/kth-smallest-element-in-a-sorted-matrix/)
31+
32+
此题使用 heap 来做并不是最优做法,相当于 N 个 sorted list 里找第 k 个最小,列有序的条件没有充分利用,但是却是比较容易想且比较通用的做法。
33+
34+
```Python
35+
class Solution:
36+
def kthSmallest(self, matrix: List[List[int]], k: int) -> int:
37+
38+
N = len(matrix)
39+
40+
min_heap = []
41+
for i in range(min(k, N)): # 这里用了一点列有序的性质,第k个最小只可能在前k行中(k行以后的数至少大于了k个数)
42+
min_heap.append((matrix[i][0], i, 0))
43+
44+
heapq.heapify(min_heap)
45+
46+
while k > 0:
47+
num, r, c = heapq.heappop(min_heap)
48+
49+
if c < N - 1:
50+
heapq.heappush(min_heap, (matrix[r][c + 1], r, c + 1))
51+
52+
k -= 1
53+
54+
return num
55+
```
56+
57+
### [find-k-pairs-with-smallest-sums](https://leetcode-cn.com/problems/find-k-pairs-with-smallest-sums/)
58+
59+
```Python
60+
class Solution:
61+
def kSmallestPairs(self, nums1: List[int], nums2: List[int], k: int) -> List[List[int]]:
62+
63+
m, n = len(nums1), len(nums2)
64+
result = []
65+
66+
if m * n == 0:
67+
return result
68+
69+
min_heap = [(nums1[0] + nums2[0], 0, 0)]
70+
seen = set()
71+
72+
while min_heap and len(result) < k:
73+
_, i1, i2 = heapq.heappop(min_heap)
74+
result.append([nums1[i1], nums2[i2]])
75+
if i1 < m - 1 and (i1 + 1, i2) not in seen:
76+
heapq.heappush(min_heap, (nums1[i1 + 1] + nums2[i2], i1 + 1, i2))
77+
seen.add((i1 + 1, i2))
78+
if i2 < n - 1 and (i1, i2 + 1) not in seen:
79+
heapq.heappush(min_heap, (nums1[i1] + nums2[i2 + 1], i1, i2 + 1))
80+
seen.add((i1, i2 + 1))
81+
82+
return result
83+
```
84+
85+
## Greedy + Heap
86+
87+
Heap 可以高效地取出或更新当前池中优先级最高的元素,因此适用于一些需要 greedy 算法的场景。
88+
89+
### [ipo](https://leetcode-cn.com/problems/ipo/)
90+
91+
**图森面试真题**。贪心策略为每次做当前成本范围内利润最大的项目。
92+
93+
```Python
94+
class Solution:
95+
def findMaximizedCapital(self, k: int, W: int, Profits: List[int], Capital: List[int]) -> int:
96+
N = len(Profits)
97+
projects = sorted([(-Profits[i], Capital[i]) for i in range(N)], key=lambda x: x[1])
98+
99+
projects.append((0, float('inf')))
100+
101+
max_profit_heap = []
102+
103+
for i in range(N + 1):
104+
while projects[i][1] > W and len(max_profit_heap) > 0 and k > 0:
105+
W -= heapq.heappop(max_profit_heap)
106+
k -= 1
107+
108+
if projects[i][1] > W or k == 0:
109+
break
110+
111+
heapq.heappush(max_profit_heap, projects[i][0])
112+
113+
return W
114+
```
115+
116+
### [meeting-rooms-ii](https://leetcode-cn.com/problems/meeting-rooms-ii/)
117+
118+
**图森面试真题**。此题用 greedy + heap 解并不是很 intuitive,存在复杂度相同但更简单直观的做法。
119+
120+
```Python
121+
class Solution:
122+
def minMeetingRooms(self, intervals: List[List[int]]) -> int:
123+
124+
if len(intervals) == 0: return 0
125+
126+
intervals.sort(key=lambda item: item[0])
127+
end_times = [intervals[0][1]]
128+
129+
for interval in intervals[1:]:
130+
if end_times[0] <= interval[0]:
131+
heapq.heappop(end_times)
132+
133+
heapq.heappush(end_times, interval[1])
134+
135+
return len(end_times)
136+
```
137+
138+
### [reorganize-string](https://leetcode-cn.com/problems/reorganize-string/)
139+
140+
```Python
141+
class Solution:
142+
def reorganizeString(self, S: str) -> str:
143+
144+
max_dup = (len(S) + 1) // 2
145+
counts = collections.Counter(S)
146+
147+
heap = []
148+
for c, f in counts.items():
149+
if f > max_dup:
150+
return ''
151+
heap.append([-f, c])
152+
heapq.heapify(heap)
153+
154+
result = []
155+
while len(heap) > 1:
156+
first = heapq.heappop(heap)
157+
result.append(first[1])
158+
first[0] += 1
159+
second = heapq.heappop(heap)
160+
result.append(second[1])
161+
second[0] += 1
162+
163+
if first[0] < 0:
164+
heapq.heappush(heap, first)
165+
if second[0] < 0:
166+
heapq.heappush(heap, second)
167+
168+
if len(heap) == 1:
169+
result.append(heap[0][1])
170+
171+
return ''.join(result)
172+
```
173+
174+
## Dijkstra's Algorithm
175+
176+
本质上也是 greedy + heap 的一种,用于求解图的单源最短路径相关的问题。
177+
178+
### [network-delay-time](https://leetcode-cn.com/problems/network-delay-time/)
179+
180+
标准的单源最短路径问题,使用朴素的的 Dijikstra 算法即可,可以当成模板使用。
181+
182+
```Python
183+
class Solution:
184+
def networkDelayTime(self, times: List[List[int]], N: int, K: int) -> int:
185+
186+
# construct graph
187+
graph_neighbor = collections.defaultdict(list)
188+
for s, e, t in times:
189+
graph_neighbor[s].append((e, t))
190+
191+
# Dijkstra
192+
SPT = {}
193+
min_heap = [(0, K)]
194+
195+
while min_heap:
196+
delay, node = heapq.heappop(min_heap)
197+
if node not in SPT:
198+
SPT[node] = delay
199+
for n, d in graph_neighbor[node]:
200+
if n not in SPT:
201+
heapq.heappush(min_heap, (d + delay, n))
202+
203+
return max(SPT.values()) if len(SPT) == N else -1
204+
```
205+
206+
### [cheapest-flights-within-k-stops](https://leetcode-cn.com/problems/cheapest-flights-within-k-stops/)
207+
208+
在标准的单源最短路径问题上限制了路径的边数,因此需要同时维护当前 SPT 内每个结点最短路径的边数,当遇到边数更小的路径 (边权和可以更大) 时结点需要重新入堆,以更新后继在边数上限内没达到的结点。
209+
210+
```Python
211+
class Solution:
212+
def findCheapestPrice(self, n: int, flights: List[List[int]], src: int, dst: int, K: int) -> int:
213+
214+
# construct graph
215+
graph_neighbor = collections.defaultdict(list)
216+
for s, e, p in flights:
217+
graph_neighbor[s].append((e, p))
218+
219+
# modified Dijkstra
220+
prices, steps = {}, {}
221+
min_heap = [(0, 0, src)]
222+
223+
while len(min_heap) > 0:
224+
price, step, node = heapq.heappop(min_heap)
225+
226+
if node == dst: # early return
227+
return price
228+
229+
if node not in prices:
230+
prices[node] = price
231+
232+
steps[node] = step
233+
if step <= K:
234+
step += 1
235+
for n, p in graph_neighbor[node]:
236+
if n not in prices or step < steps[n]:
237+
heapq.heappush(min_heap, (p + price, step, n))
238+
239+
return -1
240+
```

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /