[[max(first[0], second[0]), min(first[1], second[1])]
for first in a for second in b
if max(first[0], second[0]) <= min(first[1], second[1])]
给出答案的列表理解:[[1, 2], [5, 5], [8, 10], [15, 18], [20, 23], [24, 24]]
分解一下:
[[max(first[0], second[0]), min(first[1], second[1])]
第一项的最大值,第二项的最小值
for first in a for second in b
对于第一项和第二项的所有组合:
if max(first[0], second[0]) <= min(first[1], second[1])]
仅当第一个的最大值不超过第二个的最小值时。
如果您需要压缩输出,那么以下函数可以做到这一点(在O(n^2)
时间,因为从列表中删除是O(n)
,我们执行的一个步骤O(n)
times):
def reverse_compact(lst):
for index in range(len(lst) - 2,-1,-1):
if lst[index][1] + 1 >= lst[index + 1][0]:
lst[index][1] = lst[index + 1][1]
del lst[index + 1] # remove compacted entry O(n)*
return lst
它连接接触的范围,因为它们是in-order。它以相反的方式进行,因为这样我们就可以执行此操作in place并删除压缩的条目。如果我们不反过来做,删除其他条目就会破坏我们的索引。
>>> reverse_compact(comp)
[[1, 2], [5, 5], [8, 10], [15, 18], [20, 24]]
- 压缩函数可以进一步简化为
O(n)
通过进行前向就地压缩并复制回元素,因为每个内部步骤都是O(1)
(get/set 而不是 del),但这可读性较差:
这运行在O(n)
时间和空间复杂度:
def compact(lst):
next_index = 0 # Keeps track of the last used index in our result
for index in range(len(lst) - 1):
if lst[next_index][1] + 1 >= lst[index + 1][0]:
lst[next_index][1] = lst[index + 1][1]
else:
next_index += 1
lst[next_index] = lst[index + 1]
return lst[:next_index + 1]
使用任一压缩器,列表理解是这里的主导术语,时间 =O(n*m)
, 空间 =O(m+n)
,因为它比较两个列表的所有可能组合,没有早期出局。这确实not利用提示中给出的列表的有序结构:您可以利用该结构将时间复杂度降低到O(n + m)
因为它们总是增加并且从不重叠,这意味着您可以一次完成所有比较。
请注意,解决方案不止一种,希望您能够解决问题,然后迭代改进它。
满足所有可能输入的 100% 正确答案并不是面试问题的目标。就是看一个人如何思考和应对挑战,以及是否能够推理出解决方案。
事实上,如果你给我一个 100% 正确的教科书答案,那可能是因为你以前见过这个问题并且你已经知道解决方案......因此这个问题对我作为面试官没有帮助。“检查一下,可以反省在 StackOverflow 上找到的解决方案。”这个想法是看着你解决问题,而不是重复解决方案。
太多的候选人只见树木,不见森林:承认缺点并提出解决方案是回答面试问题的正确方法。你不必有解决方案,你必须展示你将如何解决问题。
如果可以的话你的解决方案很好解释一下并详细说明使用它的潜在问题。
我通过未能回答面试问题获得了现在的工作:在花费了大部分时间尝试之后,我解释了为什么我的方法不起作用,以及如果有更多时间我会尝试第二种方法,以及我在其中看到的潜在陷阱方法(以及为什么我最初选择第一个策略)。