一、问题描述
有三个区间,分别为:
[l_1, r_1]、[l_2, r_2]、[l_3, r_3];
小C和小U从这些区间中各自选择一个区间,并且选择的两个区间不可以相同。接着,他们从自己的区间内选择一个数,要求这个数还要能够在对方的区间内找到。他们希望获得两个数的和尽可能大。
我们的任务是帮助小C和小U找到这两个数的和的最大值。如果不存在满足条件的两个数,输出 -1。
二、问题分析
-
区间重合问题:
- 小C和小U分别从各自的区间中选择一个数。为了保证这个数既能满足自己的区间,又能满足对方的区间,这两个区间必须有重合部分。我们需要找到这些区间的重合部分。
-
区间选择:
- 每对区间
[l1, r1]和[l2, r2],它们的重合部分的最大值将是这两个区间交集的最大值。即,如果这两个区间有交集[l, r],那么r就是所能选择的最大的数。
- 每对区间
-
目标:
- 两人都选择重合区间中最大的数
m,最大和=2*m, 即所求目标。
- 两人都选择重合区间中最大的数
-
边界条件:
- 如果三个区间中,任意两个都没有交集,那么小C和小U无法选取满足条件的数,返回
-1。
- 如果三个区间中,任意两个都没有交集,那么小C和小U无法选取满足条件的数,返回
三、解题思路
-
区间重合计算:
- 给定两个区间
[a, b]和[c, d],它们的交集是[max(a, c), min(b, d)]。如果max(a, c) <= min(b, d),说明两个区间有交集,交集的最大值为min(b, d)。 - 如果没有交集,即
max(a, c) > min(b, d),则两个区间无法选取共同的数,返回-∞。
- 给定两个区间
-
重合区间选择:
- 计算每对区间的交集后,取所有交集的最大值。这就是我们选择的最大的数,然后返回这个值的两倍作为最终结果。
- 如果所有的交集最大值都是无穷小(即没有交集),返回
-1。
四、代码实现
import math
def solution(l1: int, r1: int, l2: int, r2: int, l3: int, r3: int) -> int:
# 计算三个区间对之间的重合部分
n1 = find_overlap(l1, r1, l2, r2)
n2 = find_overlap(l2, r2, l3, r3)
n3 = find_overlap(l3, r3, l1, r1)
# 计算所有重合区间中的最大值
maximum = max(n1, n2, n3)
# 如果没有重合区间,返回-1
if math.isinf(maximum) and maximum < 0:
return -1
# 返回最大重合区间数的两倍
return maximum * 2
def find_overlap(a: int, b: int, c: int, d: int):
# 如果重合,返回重合区间内的最大值
if max(a,c) <= min(b,d):
return min(b,d)
# 如果没有重合部分,返回无穷小
return float('-inf')
if __name__ == '__main__':
print(solution(1, 3, 2, 4, 4, 6) == 8) # 输出 8
print(solution(1, 2, 2, 3, 3, 4) == 6) # 输出 6
print(solution(10, 20, 15, 25, 30, 40) == 40) # 输出 40
五、复杂度分析
-
时间复杂度:
find_overlap函数每次调用的时间复杂度为O(1),它只是做了几个条件判断和简单的计算。- 由于我们只调用了
find_overlap三次,整个solution函数的时间复杂度是O(1)。
-
空间复杂度:
- 函数只使用了常数空间来存储临时变量,因此空间复杂度是
O(1)。
- 函数只使用了常数空间来存储临时变量,因此空间复杂度是
六、总结与收获
通过这道题,我学习到了如何处理区间交集的问题,并应用了区间重合计算的方法来解决具体问题。代码实现上,我们通过找出三个区间对的交集,找到最大交集值,并通过简单的数学运算得到最终结果。对于区间类的问题,理解如何高效地计算交集和最大值是非常重要的。
这道题的解法是直接而高效的,并且时间复杂度保持在常数级别,说明在处理一些较为简单的问题时,简洁而直接的解决方案是值得优先考虑的。在实际编程中,良好的代码结构和清晰的思路同样重要。