问题描述
小C和小U一直相互喜欢着,今天他们终于有机会表达对彼此的心意。
小C有三个区间:[l_1, r_1]
, [l_2, r_2]
, 和 [l_3, r_3]
。小C和小U将分别从这些区间中选择一个自己最喜欢的区间,但这两个区间不能相同。
接着,他们会在自己喜欢的区间内选择一个数,并且这个数还要能够在对方的区间内找到。为了讨对方欢心,他们希望选择的两个数的和尽可能大。
你的任务是帮助小C和小U找到这两个数的和的最大值。如果不存在这样的两个数,输出 -1
。
测试样例
样例1:
输入:
l1 = 1, r1 = 3, l2 = 2, r2 = 4, l3 = 4, r3 = 6
输出:8
样例2:
输入:
l1 = 1, r1 = 2, l2 = 2, r2 = 3, l3 = 3, r3 = 4
输出:6
样例3:
输入:
l1 = 10, r1 = 20, l2 = 15, r2 = 25, l3 = 30, r3 = 40
输出:40
C++解题
问题理解
小C和小U分别从三个区间中选择一个区间,并且这两个区间不能相同。然后,他们各自在自己的区间内选择一个数,并且这个数还要能够在对方的区间内找到。目标是找到这两个数的和的最大值。
数据结构选择
由于我们只需要处理区间和数值,不需要复杂的数据结构。我们可以直接使用整数和区间来表示问题中的数据。
算法步骤
- 区间选择:我们需要考虑所有可能的区间组合(三个区间中选择两个不同的区间)。
- 数值选择:对于每一对选择的区间,我们需要找到两个数,一个数在第一个区间内,另一个数在第二个区间内,并且这两个数能够在对方的区间内找到。
- 计算和:对于每一对有效的数,计算它们的和,并记录最大值。
- 返回结果:如果没有找到任何有效的数对,返回
-1
。
具体步骤
- 枚举区间对:我们可以通过两层循环来枚举所有可能的区间对。
- 检查数值:对于每一对区间,检查是否存在两个数满足条件。
- 更新最大和:如果找到满足条件的数对,更新最大和。
代码实现
#include <iostream>
#include <vector>
#include <string>
#include <algorithm> // for std::max
using namespace std;
int solution(int l1, int r1, int l2, int r2, int l3, int r3) {
// PLEASE DO NOT MODIFY THE FUNCTION SIGNATURE
// write code here
int maxSum = -1;
// Helper function to check if a number is within a range
auto inRange = [](int num, int l, int r) {
return num >= l && num <= r;
};
// Try all combinations of two different intervals
vector<pair<int, int>> intervals = {{l1, r1}, {l2, r2}, {l3, r3}};
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
if (i == j) continue; // Skip the same interval
int l1 = intervals[i].first, r1 = intervals[i].second;
int l2 = intervals[j].first, r2 = intervals[j].second;
// Try to find the maximum sum
for (int num1 = r1; num1 >= l1; --num1) {
for (int num2 = r2; num2 >= l2; --num2) {
if (inRange(num1, l2, r2) && inRange(num2, l1, r1)) {
maxSum = max(maxSum, num1 + num2);
}
}
}
}
}
return maxSum;
}
int main() {
cout << (solution(1, 3, 2, 4, 4, 6) == 8) << endl;
cout << (solution(1, 2, 2, 3, 3, 4) == 6) << endl;
cout << (solution(10, 20, 15, 25, 30, 40) == 40) << endl;
}
Python解题
思路说明
题目要求在三个区间中分别选择两个不同的区间,并在各自的区间内选择一个数,使得这两个数的和尽可能大,并且这两个数还要在对方的区间内存在。为了最大化这两个数的和,我们可以考虑在每个区间中选择最大的数,然后检查这两个数是否在对方的区间内。如果存在这样的两个数,则它们的和就是我们要找的最大值。
解题过程
- 区间表示:将三个区间表示为
(l1, r1)
,(l2, r2)
,(l3, r3)
。 - 区间交集:定义一个辅助函数
solution(s1, s2)
,用于计算两个区间的交集。如果两个区间没有交集,则返回-1
;否则返回交集区间的右端点。 - 遍历所有区间对:通过双重循环遍历所有可能的区间对
(seg[i], seg[j])
,其中i
和j
是不同的区间索引。 - 计算最大和:对于每一对区间
(seg[i], seg[j])
,计算它们的交集,并更新最大和。如果交集存在,则交集区间的右端点乘以2就是当前的最大和。 - 返回结果:最终返回计算得到的最大和。
复杂度分析
- 时间复杂度:由于我们使用了双重循环来遍历所有区间对,时间复杂度为 O(n2),其中 n=3,所以实际时间复杂度为 O(1)。
- 空间复杂度:只使用了常数级别的额外空间,空间复杂度为 O(1)。
知识点扩展
- 区间操作:区间操作是算法中常见的问题,涉及到区间的交集、并集、补集等操作。在这道题目中,我们主要使用了区间的交集操作来判断两个区间是否有重叠部分。
- 贪心算法:贪心算法是一种在每一步选择中都采取在当前状态下最好或最优的选择,从而希望导致结果是全局最好或最优的算法。在这道题目中,我们通过选择每个区间中的最大数来尝试最大化两个数的和。
代码实现
def solution(l1: int, r1: int, l2: int, r2: int, l3: int, r3: int):
assert l1 <= r1 and l2 <= r2 and l3 <= r3
seg = [(l1, r1), (l2, r2), (l3, r3)]
def solution(s1, s2):
s = (max(s1[0], s2[0]), min(s1[1], s2[1]))
return -1 if s[0] > s[1] else s[1]
ans = -1
for i in range(len(seg)):
for j in range(i):
k = solution(seg[i], seg[j])
if k >= 0:
ans = max(ans, k * 2)
return ans
if __name__ == '__main__':
print(solution(l1 = 1, r1 = 3, l2 = 2, r2 = 4, l3 = 4, r3 = 6) == 8)
print(solution(l1 = 1, r1 = 2, l2 = 2, r2 = 3, l3 = 3, r3 = 4) == 6)
print(solution(l1 = 10, r1 = 20, l2 = 15, r2 = 25, l3 = 30, r3 = 40) == 40)