题目描述
给定两个数组,编写一个函数来计算它们的交集。
示例1
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]
示例2
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
说明
- 输出结果中的每个元素一定是唯一的
- 物品们可以不考虑输出结果的顺序
方法一:两个集合
JAVA代码
算法思想
新建集合1和集合2,首先遍历第一个数组并去重,并存放在集合1中,然后遍历第二个数组,对于第二个数组中的每个元素,如果该元素在集合1中,则将该元素存放到集合2中,遍历完成后,将集合2中的元素存放到一个新建的数组中,返回该数组
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
Set<Integer> parentSet = new HashSet<Integer>();
Set<Integer> childSet = new HashSet<Integer>();
for (int num : nums1) {
parentSet.add(num);
}
for (int num : nums2) {
if (parentSet.contains(num)) {
childSet.add(num);
}
}
int[] newArr = new int[childSet.size()];
int index = 0;
for (int num : childSet) {
newArr[index++] = num;
}
return newArr;
}
}
复杂度分析
时间复杂度:O(m+n),其中 m 和 n 分别是两个数组的长度。使用两个集合分别存储两个数组中的元素需要 O(m+n) 的时间,遍历较小的集合并判断元素是否在另一个集合中需要 O(min(m,n)) 的时间,因此总时间复杂度是 O(m+n)。
空间复杂度:O(m+n),其中 m 和 n 分别是两个数组的长度。空间复杂度主要取决于两个集合。
方法二:排序+双指针
算法思想
首先新建一个集合,对两个数组进行排序,然后使用两个指针遍历两个数组。
初始时,两个指针分别指向两个数组的头部。每次比较两个指针指向的两个数组中的数字,如果两个数字不相等,则将指向较小数字的指针右移一位,如果两个数字相等,则将该数字添加到集合,同时将两个指针都右移一位。当至少有一个指针超出数组范围时,遍历结束
最后,将集合中的元素存放到数组中并返回数组
JAVA代码
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
Arrays.sort(nums1);
Arrays.sort(nums2);
int i = 0, j = 0;
Set<Integer> nums = new HashSet<Integer>();
while (i < nums1.length && j < nums2.length) {
if (nums1[i] == nums2[j]) {
nums.add(nums1[i]);
} else if (nums1[i] < nums2[j]) {
++i;
} else if (nums1[i] > nums2[j]) {
++j;
}
}
int[] newArr = new int[nums.size()];
int index = 0;
for (int num : nums) {
newArr[index++] = num;
}
return newArr;
}
}
复杂度分析
时间复杂度:O(mlogm+nlogn),其中 m 和 n 分别是两个数组的长度。对两个数组排序的时间复杂度分别是 O(mlogm) 和 O(nlogn),双指针寻找交集元素的时间复杂度是 O(m+n),因此总时间复杂度是 O(mlogm+nlogn)。
空间复杂度:O(logm+logn),其中 m 和 n 分别是两个数组的长度。空间复杂度主要取决于排序使用的额外空间。