Medium
题目描述
给你两个长度为 n 的整数数组 x 和 y。你必须选择三个不同的索引 i、j 和 k,使得:
- x[i] != x[j]
- x[j] != x[k]
- x[k] != x[i]
你的目标是在这些条件下最大化 y[i] + y[j] + y[k] 的值。返回通过选择这样的三元组索引可以获得的最大可能和。
如果不存在这样的三元组,返回 -1。
示例 1:
输入:x = [1,2,1,3,2], y = [5,3,4,6,2]
输出:14
解释:
选择 i = 0(x[i] = 1, y[i] = 5)、j = 1(x[j] = 2, y[j] = 3)、k = 3(x[k] = 3, y[k] = 6)。
从 x 中选择的三个值都不相同。5 + 3 + 6 = 14 是我们能获得的最大值。因此输出是 14。
示例 2:
输入:x = [1,2,1,2], y = [4,5,6,7]
输出:-1
解释:
x 中只有两个不同的值。因此输出是 -1。
约束条件:
- n == x.length == y.length
- 3 <= n <= 10^5
- 1 <= x[i], y[i] <= 10^6
解题思路
这道题要求我们从数组中选择三个不同 x 值对应的 y 值,使其和最大。
核心思路:
- 对于相同的 x 值,我们只需要保留对应的最大 y 值,因为选择更大的 y 值总是更优的
- 将所有不同的 x 值及其对应的最大 y 值收集起来
- 如果不同的 x 值少于 3 个,直接返回 -1
- 从所有候选对中选择 y 值最大的三个即可
算法步骤:
- 使用哈希表记录每个 x 值对应的最大 y 值
- 将所有 (x, max_y) 对提取出来
- 按 y 值降序排序,选择前三个 y 值求和
这种方法的正确性在于:由于我们需要三个不同的 x 值,而对于每个 x 值我们只能选择一次,所以贪心地选择每个 x 值对应的最大 y 值,然后从中选择 y 值最大的三个组合即可获得最优解。
时间复杂度主要来自排序操作。
代码实现
class Solution {
public:
int maxSumDistinctTriplet(vector<int>& x, vector<int>& y) {
unordered_map<int, int> maxY;
// 对每个x值保留最大的y值
for (int i = 0; i < x.size(); i++) {
maxY[x[i]] = max(maxY[x[i]], y[i]);
}
// 如果不同的x值少于3个,返回-1
if (maxY.size() < 3) {
return -1;
}
// 提取所有y值并排序
vector<int> yValues;
for (auto& pair : maxY) {
yValues.push_back(pair.second);
}
sort(yValues.rbegin(), yValues.rend());
return yValues[0] + yValues[1] + yValues[2];
}
};
class Solution:
def maxSumDistinctTriplet(self, x: List[int], y: List[int]) -> int:
max_y = {}
# 对每个x值保留最大的y值
for i in range(len(x)):
max_y[x[i]] = max(max_y.get(x[i], 0), y[i])
# 如果不同的x值少于3个,返回-1
if len(max_y) < 3:
return -1
# 提取所有y值并排序
y_values = list(max_y.values())
y_values.sort(reverse=True)
return y_values[0] + y_values[1] + y_values[2]
public class Solution {
public int MaxSumDistinctTriplet(int[] x, int[] y) {
Dictionary<int, int> maxY = new Dictionary<int, int>();
// 对每个x值保留最大的y值
for (int i = 0; i < x.Length; i++) {
if (maxY.ContainsKey(x[i])) {
maxY[x[i]] = Math.Max(maxY[x[i]], y[i]);
} else {
maxY[x[i]] = y[i];
}
}
// 如果不同的x值少于3个,返回-1
if (maxY.Count < 3) {
return -1;
}
// 提取所有y值并排序
List<int> yValues = new List<int>(maxY.Values);
yValues.Sort((a, b) => b.CompareTo(a));
return yValues[0] + yValues[1] + yValues[2];
}
}
var maxSumDistinctTriplet = function(x, y) {
const maxY = new Map();
// 对每个x值保留最大的y值
for (let i = 0; i < x.length; i++) {
maxY.set(x[i], Math.max(maxY.get(x[i]) || 0, y[i]));
}
// 如果不同的x值少于3个,返回-1
if (maxY.size < 3) {
return -1;
}
// 提取所有y值并排序
const yValues = Array.from(maxY.values());
yValues.sort((a, b) => b - a);
return yValues[0] + yValues[1] + yValues[2];
};
复杂度分析
| 复杂度 | 值 |
|---|---|
| 时间复杂度 | O(n log k),其中 n 是数组长度,k 是不同 x 值的个数,主要消耗在排序上 |
| 空间复杂度 | O(k),用于存储哈希表和 y 值数组,其中 k 是不同 x 值的个数 |