Skip to content

Commit 93546cf

Browse files
author
aaron.liu
committed
update
1 parent 635de65 commit 93546cf

14 files changed

+352
-51
lines changed

Array/Meta_two_sum_max.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
from typing import List
2-
import sys
1+
from typing import List
32
'''
43
给定一个nums数组 返回数组中两个元素的最大和. 要求这两个元素不能相邻.
54

Linkedin/tallest tower.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ def max_tower_height(blocks: List[List[int]]) -> int:
3939

4040
# 尝试使用当前砖块
4141
for k in range(1, count + 1):
42+
# 当前重量是j 用了k块重weight的砖 所以之前的状态重量是:(j-k*weight)
43+
# 之前的状态必须合法 所以j-k*weight >= 0
44+
# 当前的重量必须要在当前砖的承受力之内:j<=max_support
4245
if j >= k * weight and j <= max_support:
4346
dp[i][j] = max(dp[i][j], dp[i - 1][j - k * weight] + k)
4447

@@ -58,8 +61,8 @@ def max_tower_height(blocks: List[List[int]]) -> int:
5861
# followup: 如果每块砖的高度不一样
5962
# 还是按照承重能力从小到大排序
6063
def max_tower_height_w(blocks):
61-
# 按承重能力从小到大排序
62-
blocks.sort(key=lambda x: x[2])
64+
# 按(承重能力递增,高度递减)排序:先用 承重差且高度高的blocks
65+
blocks.sort(key=lambda x: (x[2], -x[3]))
6366

6467
n = len(blocks)
6568
max_weight = max(block[2] for block in blocks)

Meta/merge k interval lists.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
'''
2+
https://www.1point3acres.com/bbs/forum.php?mod=viewthread&tid=1073573&page=1#pid19674457
3+
求 intersection of K lists of intervals
4+
我们定义了一个辅助函数 merge_two_interval_lists 用于合并两个区间列表并找出它们的交集。
5+
在主函数 find_intersection 中,我们使用分治的思想:
6+
如果只有一个列表,直接返回。
7+
否则,将列表分成两半,分别递归处理。
8+
最后,合并两个子问题的结果。
9+
10+
时间复杂度分析:
11+
假设有 k 个列表,总共有 n 个区间。
12+
合并两个列表的时间复杂度是 O(n),因为我们只需要遍历一次两个列表。
13+
我们需要进行 log k 次合并操作(因为每次都将问题规模减半)。
14+
因此,总的时间复杂度是 O(n log k)。
15+
16+
空间复杂度分析:
17+
递归调用栈的深度是 O(log k)。
18+
在每一层递归中,我们都需要 O(n) 的空间来存储中间结果。
19+
20+
另一种解法: for each interval list[i] 与第i-1个interval list merge
21+
时间复杂度O(k*n)
22+
'''
23+
from typing import List
24+
25+
def merge_two_interval_lists(list1:List[int], list2:List[int]):
26+
i, j = 0, 0
27+
result = []
28+
while i < len(list1) and j < len(list2):
29+
# 找到两个区间的交集
30+
start = max(list1[i][0], list2[j][0])
31+
end = min(list1[i][1], list2[j][1])
32+
# 如果有交集,添加到结果中
33+
if start <= end:
34+
result.append([start, end])
35+
# 移动指针
36+
if list1[i][1] < list2[j][1]:
37+
i += 1
38+
else:
39+
j += 1
40+
return result
41+
42+
def find_intersection(intervals:List[List[List[int]]]) -> List[List[int]]:
43+
if not intervals:
44+
return []
45+
if len(intervals) == 1:
46+
return intervals[0]
47+
48+
# 使用分治法
49+
mid = len(intervals) // 2
50+
left = find_intersection(intervals[:mid])
51+
right = find_intersection(intervals[mid:])
52+
53+
# 合并两个结果
54+
return merge_two_interval_lists(left, right)
55+
56+
# 测试用例
57+
intervals1 = [
58+
[[1,5], [10,14], [16,18]],
59+
[[2,6], [8,10], [11,20]],
60+
[[3,7], [9,12], [15,19]]
61+
]
62+
63+
intervals2 = [
64+
[[0,2],[5,10],[13,23],[24,25]],
65+
[[1,5],[8,12],[15,24],[25,26]]
66+
]
67+
68+
intervals3 = [
69+
[[1,3],[5,9]],
70+
[]
71+
]
72+
print(find_intersection(intervals1)) # [[3, 5], [10, 10], [11, 12], [16, 18]]
73+
print(find_intersection(intervals2)) # [[1, 2], [5, 5], [8, 10], [15, 23], [24, 24], [25, 25]]
74+
print(find_intersection(intervals3)) # []

Meta/test.py

Whitespace-only changes.

Pins/LC1055 Shortest Way to Form String.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
2929
思路:
3030
1.用一个二维哈希表(或者二维数组)index_to_next来表示当前source的index右边(包括index本身)每一个字母第一次出现的位置的下一个位置。
31-
比如abbc 那么index[0]['a']=1 index[0]['b'] = 2, index[1]['b']= 2, index[2]['b']= 3..从右向左遍历一遍source即可完成更新index_to_next
31+
比如abbc 那么index[0]['a']= 1 index[0]['b'] = 2, index[1]['b']= 2, index[2]['b']= 3..从右向左遍历一遍source即可完成更新index_to_next
3232
2.然后遍历target, source和target的位置分别记为i和j 我们执行以下操作:
3333
1.index_to_next[0]当中是否存在target[j] 即整个source中是否存在j 不存在则返回-1
3434
2.index_to_next[i]当中是否存在target[j] 如果不存在 说明source在位置i右侧不存在target[j] i应当归零从头开始找

Pins/LC157 Read N Characters Given Read4.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
'''
22
https://leetcode.com/problems/read-n-characters-given-read4/description/
3-
43
'''
54
"""
65
The read4 API is already defined for you.

Pins/LC465 Optimal Account Balancing.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ def minTransfers(self, transactions: List[List[int]]) -> int:
4040
if not transactions:
4141
return 0
4242

43-
4443
# trans[i][0]给trans[i][1] 转了trans[i][2]块钱
4544
# 如果最终想实现平衡(每人里外里收支为零): trans[i][0]需要被给trans[i][2]块钱, trans[i][1]需要给出trans[i][2]块钱
4645
book = defaultdict(int)

Pins/available time windows for guests.py

Lines changed: 57 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,9 @@
2929
堆中的每个元素是一个 [time, seats] 对,表示某个时间点 time 和该时间点发生的座位变化 seats
3030
正数表示增加座位,负数表示减少座位。
3131
返回处理后的事件堆,包含所有预订的开始和结束时间点。
32-
2. 遍历时间堆,检查每个时间段是否可以容纳 n 人。如果可以记录这个时间段。
32+
2. 遍历时间堆 检查每个时间段是否可以容纳n人。如果可以 记录这个时间段。
3333
在遍历的过程中 通过更新当前容量cur_cap来实时跟踪可用座位情况。
34-
遍历结束后,如果最后一个事件后的时间段依然可以容纳 n 人,则将其加入结果列表。
35-
36-
34+
遍历结束后 如果最后一个事件后的时间段依然可以容纳n人 则将其加入结果列表。
3735
3836
时间复杂度: O(m*logm) 其中m是预订信息的数量
3937
空间复杂度: O(m)
@@ -65,14 +63,13 @@ def all_available_time_slots_seating_N_seating(self, n):
6563
if n > self.cap:
6664
return []
6765

68-
size = len(self.time_slots_heap)
6966
available_intervals = []
7067

7168
prev = self.opening
7269
cur_cap = self.cap
73-
for i in range(size):
74-
time, seats = self.time_slots_heap[i]
75-
70+
heap_copy = self.time_slots_heap.copy()
71+
while heap_copy:
72+
time, seats = heapq.heappop(heap_copy)
7673
# 如果当前时间 time 大于 prev(上一个时间点),且当前可用座位数 cur_cap 大于或等于 n,
7774
# 那么 [prev, time] 之间的时间段可以容纳 n 人,将其加入 result 列表。
7875
if time > prev and cur_cap >= n:
@@ -81,28 +78,27 @@ def all_available_time_slots_seating_N_seating(self, n):
8178
cur_cap += seats
8279
prev = time
8380

84-
# 如果堆中最后一个事件的时间点(heap[size - 1][0])早于餐厅关闭时间 self.close,
81+
# 如果堆中最后一个事件的时间点prev 早于餐厅关闭时间 self.close,
8582
# 说明在这个事件之后到餐厅关闭之间仍有可用时间段
86-
if self.time_slots_heap[size - 1][0] < self.close:
87-
available_intervals.append([self.time_slots_heap[size - 1][0], self.close])
83+
if prev < self.close:
84+
available_intervals.append([prev, self.close])
8885

8986
# merge intervals in available_intervals
9087
# 可用的time intervals 很可能有重叠:
9188
# 比如可能出现[[18, 19],[19, 22]] 两个区间是相邻的 可以合并为 [[18, 22]]
9289
ret = []
93-
94-
start = available_intervals[0][0]
95-
end = available_intervals[0][1]
96-
size = len(available_intervals)
97-
for i in range(size):
98-
if end >= available_intervals[i][0]:
99-
# merge these
100-
end = max(end, available_intervals[i][1])
101-
else:
102-
ret.append([start, end])
103-
start = available_intervals[i][0]
104-
end = available_intervals[i][1]
105-
ret.append([start, end])
90+
if available_intervals:
91+
start = available_intervals[0][0]
92+
end = available_intervals[0][1]
93+
94+
for interval in available_intervals[1:]:
95+
if end >= interval[0]:
96+
end = max(end, interval[1])
97+
else:
98+
ret.append([start, end])
99+
start = interval[0]
100+
end = interval[1]
101+
ret.append([start, end])
106102
return ret
107103

108104
# unit test
@@ -117,9 +113,7 @@ def all_available_time_slots_seating_N_seating(self, n):
117113
{'start': 16, 'end': 20, 'ppl': 2}
118114
]
119115
}
120-
121116
rs = ReservationScheduler(restaurant)
122-
123117
print(rs.all_available_time_slots_seating_N_seating(5))
124118

125119
'''
@@ -189,7 +183,7 @@ def time_to_minutes(self, time_str: str) -> int:
189183
hour, minute = map(int, time_parts[0].split(':'))
190184
if 'PM' in time_parts[1] and hour != 12:
191185
hour += 12
192-
if 'AM' in time_parts[1] and hour == 12:
186+
elif 'AM' in time_parts[1] and hour == 12:
193187
hour = 0
194188
return hour * 60 + minute
195189

@@ -217,7 +211,7 @@ def get_time_slots_for_heap(self, reservations: list) -> list:
217211

218212
def available_capacity_intervals(self) -> dict[str, int]:
219213
result = {}
220-
heap = list(self.time_slots_heap)
214+
heap = self.time_slots_heap.copy() # 创建堆的副本,避免修改原始数据
221215

222216
prev = self.opening
223217
cur_cap = self.capacity
@@ -227,15 +221,48 @@ def available_capacity_intervals(self) -> dict[str, int]:
227221

228222
# 注意下面这里一定要写成">" 不能">=". 有可能出现同一个时间点 有两个事件的情况
229223
if time > prev:
230-
# 如果只要求输出容量大于或等于K的时间段 这里加逻辑:if cur_cap >= K:
231224
result[f"{self.minutes_to_time(prev)}-{self.minutes_to_time(time)}"] = cur_cap
232225
cur_cap += change
233226
prev = time
234227

235228
# 处理营业时间结束前的最后一个时间段
236-
if prev < self.closing: # and cur_cap >= K: (如果只要求输出容量大于或等于K的时间段)
229+
if prev < self.closing:
237230
result[f"{self.minutes_to_time(prev)}-{self.minutes_to_time(self.closing)}"] = cur_cap
231+
return result
232+
233+
# 题目如果要求只输出容量大于或等于k的时间段
234+
def available_capacity_intervals_for_K(self, k) -> dict[str, int]:
235+
result = {}
236+
heap = self.time_slots_heap.copy() # 创建堆的副本,避免修改原始数据
238237

238+
prev = self.opening
239+
cur_cap = self.capacity
240+
241+
# 用来跟踪上一个有效时间段的结束时间。
242+
# 有助于我们合并连续的有效时间段。
243+
last_valid_time = self.opening
244+
245+
while heap:
246+
time, change = heapq.heappop(heap)
247+
if time > prev:
248+
if cur_cap >= k:
249+
if prev > last_valid_time:
250+
result[f"{self.minutes_to_time(prev)}-{self.minutes_to_time(time)}"] = cur_cap
251+
else:
252+
result[f"{self.minutes_to_time(last_valid_time)}-{self.minutes_to_time(time)}"] = cur_cap
253+
last_valid_time = time
254+
elif prev < last_valid_time:
255+
result[f"{self.minutes_to_time(last_valid_time)}-{self.minutes_to_time(prev)}"] = result.get(f"{self.minutes_to_time(last_valid_time)}-{self.minutes_to_time(prev)}", cur_cap)
256+
last_valid_time = prev
257+
cur_cap += change
258+
prev = time
259+
260+
# 处理营业时间结束前的最后一个时间段
261+
if prev < self.closing and cur_cap >= k:
262+
if prev > last_valid_time:
263+
result[f"{self.minutes_to_time(prev)}-{self.minutes_to_time(self.closing)}"] = cur_cap
264+
else:
265+
result[f"{self.minutes_to_time(last_valid_time)}-{self.minutes_to_time(self.closing)}"] = cur_cap
239266
return result
240267

241268
# unit test

Pins/bi-partite image sets.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ def divideImages(pairs: List[List[int]]) -> List[List[str]]:
7171

7272
return [group1, group2]
7373

74-
7574
# unit test case 1
7675
pairs = [["I_1", "I_4"], ["I_4", "I_8"], ["I_8", "I_2"]]
7776
print(divideImages(pairs)) # [['I_1', 'I_8'], ['I_4', 'I_2']]

Pins/candidate score greater than K others.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
77
e.g
88
es = [1, 2, 3, 4, 5]
9-
rs = [1,2, 3, 4, 5]
9+
rs = [1, 2, 3, 4, 5]
1010
K = 1
1111
Output: 4 since all candidates except the 0th one have at least one other candidate
1212
where its engagement and relevance score is greater than another candidate
@@ -23,6 +23,11 @@
2323
3.统计剩余候选人
2424
最后统计rs优先队列中剩下的候选人数量 这个数量就是符合条件的候选人数量。
2525
26+
注意: We need to keep track of the elements removed from the rs priority queue by storing them in a set,
27+
and shouldn't start the delete process if the element is already removed.
28+
Otherwise we'll end up deleting all the elements from rs priority queue,
29+
because we'll never find the target element.
30+
2631
时间复杂度为 O(n log n)
2732
空间复杂度为 O(n)
2833
'''
@@ -46,13 +51,16 @@ def find_greater_than_k_others(es:List[int], rs:List[int], k:int) -> int:
4651
# 删除前k个得分最低的候选人
4752
while k:
4853
es_score, index = heapq.heappop(es_pq)
54+
# remove that element from the rs priority queue,
55+
# along with all the other elements lower than that.
4956
if index not in removed:
5057
while rs_pq and rs_pq[0][1] != index:
5158
_, popped_index = heapq.heappop(rs_pq)
5259
removed.add(popped_index) # 注意这里需要把index加到removed set中
5360
# 删除对应的rs中的元素
54-
heapq.heappop(rs_pq)
55-
removed.add(index)
61+
if rs_pq:
62+
heapq.heappop(rs_pq)
63+
removed.add(index)
5664
k -= 1
5765
# 剩余候选人数量即为答案
5866
return len(rs_pq)

0 commit comments

Comments
 (0)