题目描述:349. 两个数组的交集 - 力扣(LeetCode)
给定两个数组
nums1
和nums2
,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。
方法一:
解题思路:
我们可以采用排序和双指针的方法来求两个数组的交集。
对两个输入数组
nums1
和nums2
进行排序,以便能够有效地在有序数组中查找交集元素。初始化两个指针
ptr1
和ptr2
,分别指向数组nums1
和nums2
的起始位置。创建一个结果数组,用于存储交集元素。同时,创建一个变量
count
用于记录结果数组中的元素个数。开始循环遍历两个有序数组:
- 比较
nums1[ptr1]
和nums2[ptr2]
。- 如果两个元素相等,则将这个元素添加到结果数组中,然后增加
ptr1
和ptr2
。- 如果
nums1[ptr1]
小于nums2[ptr2]
,则增加ptr1
。- 如果
nums1[ptr1]
大于nums2[ptr2]
,则增加ptr2
。循环继续,直到任一指针达到其数组的末尾。
返回结果数组,同时更新
count
为结果数组中的元素个数。
代码:
// 比较函数,用于排序
int compare(const void *a, const void *b) {
return (*(int *)a - *(int *)b);
}
int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize) {
qsort(nums1, nums1Size, sizeof(int), compare);
qsort(nums2, nums2Size, sizeof(int), compare);
int *result = (int *)malloc(sizeof(int) * (nums1Size < nums2Size ? nums1Size : nums2Size));
int count = 0;
int i = 0, j = 0;
while (i < nums1Size && j < nums2Size) {
if (nums1[i] == nums2[j]) {
// 避免重复添加相同元素
if (count == 0 || nums1[i] != result[count - 1]) {
result[count++] = nums1[i];
}
i++;
j++;
} else if (nums1[i] < nums2[j]) {
i++;
} else {
j++;
}
}
*returnSize = count;
return result;
}
方法二:
解题思路:
利用哈希集合:
初始化一个哈希集合,用于存储
nums1
数组中的元素。遍历
nums1
数组,将其中的元素加入哈希集合中。创建一个结果数组,用于存储交集元素。
遍历
nums2
数组,对于其中的每个元素,判断是否在哈希集合中出现:
- 如果出现,则将该元素加入结果数组,并从哈希集合中移除,以避免重复添加相同元素。
返回结果数组。
代码:
typedef struct
{
int *data;
int size;
} HashSet;
// 初始化哈希集合
HashSet* initHashSet()
{
HashSet* set = (HashSet*)malloc(sizeof(HashSet));
set->data = (int *)calloc(1000, sizeof(int)); // 注意初始化一定要是0
set->size = 0;
return set;
}
// 将元素加入哈希集合
void addToHashSet(HashSet* set, int num)
{
set->data[num] = 1;
set->size++;
}
// 判断元素是否在哈希集合中
int isInHashSet(HashSet* set, int num)
{
return set->data[num];
}
// 释放哈希开辟的内存
void freeHashSet(HashSet* set)
{
free(set->data);
free(set);
}
int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize)
{
HashSet* set = initHashSet();
// 将数组1中的元素添加到哈希集合中
for(int i=0;i<nums1Size;i++)
{
addToHashSet(set, nums1[i]);
}
int* ret = (int*)malloc(sizeof(int)*(nums1Size<nums2Size?nums2Size:nums1Size));
int count = 0;
// 查询
for(int i=0;i<nums2Size;i++)
{
if(isInHashSet(set, nums2[i]))
{
// 添加
ret[count++] = nums2[i];
set->data[nums2[i]] = 0; // 避免重复添加
}
}
*returnSize = count;
freeHashSet(set);
return ret;
}
总结:
哈希集合方法:
-
时间复杂度:O(m + n),其中 m 是
nums1
的长度,n 是nums2
的长度。- 创建哈希集合需要 O(m) 的时间,因为需要将
nums1
中的元素加入集合。 - 遍历
nums2
并检查元素是否在哈希集合中需要 O(n) 的时间。 - 最终的结果遍历需要 O(min(m, n)) 的时间,其中 min(m, n) 是结果数组的长度。
- 创建哈希集合需要 O(m) 的时间,因为需要将
-
空间复杂度:O(m) 或 O(n),取决于
nums1
数组的大小。- 哈希集合需要存储
nums1
中的元素,因此需要 O(m) 的额外空间。
- 哈希集合需要存储
排序和双指针方法:
-
时间复杂度:O(m * log m + n * log n + m + n),其中 m 是
nums1
的长度,n 是nums2
的长度。- 排序
nums1
和nums2
需要 O(m * log m) 和 O(n * log n) 的时间。 - 遍历两个有序数组需要 O(m + n) 的时间。
- 最终的结果遍历需要 O(min(m, n)) 的时间。
- 排序
-
空间复杂度:O(1)。
- 这种方法只使用了常量级的额外空间用于存储指针和计数。
总结起来,如果在意时间复杂度,当
m
和n
较小时,两种方法的时间复杂度都差不多,但哈希集合方法在一些特定情况下可能会稍微快一些。然而,如果在意空间复杂度,排序和双指针方法的空间复杂度更低。
本次内容到此结束了!如果你觉得这篇博客对你有帮助的话 ,希望你能够给我点个赞,鼓励一下我。感谢感谢……