Easy
题目描述
给定三个整数数组 nums1、nums2 和 nums3,返回一个不同的数组,包含至少在三个数组中的两个数组中出现的所有值。你可以按任意顺序返回这些值。
示例 1:
输入:nums1 = [1,1,3,2], nums2 = [2,3], nums3 = [3]
输出:[3,2]
解释:至少在两个数组中出现的值有:
- 3,在所有三个数组中。
- 2,在 nums1 和 nums2 中。
示例 2:
输入:nums1 = [3,1], nums2 = [2,3], nums3 = [1,2]
输出:[2,3,1]
解释:至少在两个数组中出现的值有:
- 2,在 nums2 和 nums3 中。
- 3,在 nums1 和 nums2 中。
- 1,在 nums1 和 nums3 中。
示例 3:
输入:nums1 = [1,2,2], nums2 = [4,3,3], nums3 = [5]
输出:[]
解释:没有值至少在两个数组中出现。
提示:
1 <= nums1.length, nums2.length, nums3.length <= 1001 <= nums1[i], nums2[j], nums3[k] <= 100
解题思路
本题要求找到至少在三个数组中的两个数组中出现的元素。我们可以使用以下几种思路:
思路一:集合操作(推荐) 将三个数组转换为集合(去重),然后计算两两之间的交集。最后将所有交集合并,去除重复元素。这种方法简洁直观,易于理解。
思路二:哈希表统计 使用哈希表记录每个元素在哪些数组中出现过。遍历三个数组,对于每个元素,记录它出现在的数组编号。最后统计出现在至少两个数组中的元素。
思路三:位运算优化 对于每个元素,使用一个三位的二进制数来表示它在哪些数组中出现。第0位表示在nums1中出现,第1位表示在nums2中出现,第2位表示在nums3中出现。最后筛选出二进制表示中至少有两个1的元素。
三种方法的时间复杂度都是O(n),其中n是所有数组元素的总数。考虑到代码的简洁性和可读性,推荐使用集合操作的方法。
代码实现
class Solution {
public:
vector<int> twoOutOfThree(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3) {
unordered_set<int> set1(nums1.begin(), nums1.end());
unordered_set<int> set2(nums2.begin(), nums2.end());
unordered_set<int> set3(nums3.begin(), nums3.end());
unordered_set<int> result;
// 计算三个两两交集
for (int num : set1) {
if (set2.count(num) || set3.count(num)) {
result.insert(num);
}
}
for (int num : set2) {
if (set3.count(num)) {
result.insert(num);
}
}
return vector<int>(result.begin(), result.end());
}
};
class Solution:
def twoOutOfThree(self, nums1: List[int], nums2: List[int], nums3: List[int]) -> List[int]:
set1, set2, set3 = set(nums1), set(nums2), set(nums3)
# 计算三个两两交集的并集
result = (set1 & set2) | (set1 & set3) | (set2 & set3)
return list(result)
public class Solution {
public IList<int> TwoOutOfThree(int[] nums1, int[] nums2, int[] nums3) {
var set1 = new HashSet<int>(nums1);
var set2 = new HashSet<int>(nums2);
var set3 = new HashSet<int>(nums3);
var result = new HashSet<int>();
// 计算三个两两交集
foreach (int num in set1) {
if (set2.Contains(num) || set3.Contains(num)) {
result.Add(num);
}
}
foreach (int num in set2) {
if (set3.Contains(num)) {
result.Add(num);
}
}
return result.ToList();
}
}
var twoOutOfThree = function(nums1, nums2, nums3) {
const set1 = new Set(nums1);
const set2 = new Set(nums2);
const set3 = new Set(nums3);
const result = new Set();
// 计算三个两两交集
for (const num of set1) {
if (set2.has(num) || set3.has(num)) {
result.add(num);
}
}
for (const num of set2) {
if (set3.has(num)) {
result.add(num);
}
}
return Array.from(result);
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(n) | 其中 n = len(nums1) + len(nums2) + len(nums3),需要遍历所有元素创建集合和计算交集 |
| 空间复杂度 | O(n) | 需要存储三个集合,最坏情况下每个集合包含对应数组的所有不重复元素 |