给定两个数组,编写一个函数来计算它们的交集。
示例 1:
输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2,2]
示例 2:
输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出: [4,9]
说明:
- 输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。
- 我们可以不考虑输出结果的顺序。
进阶:
-
如果给定的数组已经排好序呢?将如何优化你的算法呢?(采用第二种算法)
-
如果 nums1 的大小比 nums2 小很多,哪种方法更优?(第二种)
-
如果 nums2 的元素存储在磁盘上,内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?(采用第一种,依次加载)
方法一:
public int[] intersect(int[] nums1, int[] nums2) {
//方法1:哈希表,将小的数组装进哈希表,key为值,value为出现的次数
//遍历大的数组,每次去查哈希表,如果有,放入新的数组,将value-1,如果此时value>0,重新放入map
//时间复杂度:O(m+n) 空间复杂度O(min(m,n))
//nums1为小数组
if (nums1.length > nums2.length) {
return intersect(nums2, nums1);
}
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums1.length; i++) {
//如果有该值,获取该值并加1,如果没有,设为1
int count = map.getOrDefault(nums1[i], 0) + 1;
map.put(nums1[i], count);
}
//结果数组
int[] num = new int[nums1.length];
int index = 0;
for (int i = 0; i < nums2.length; i++) {
//获取value值,如果没有则为0
int count = map.getOrDefault(nums2[i], 0);
//如果有value
if (count > 0) {
//放入数组,同时将count-1
num[index++] = nums2[i];
count--;
//如果count还大于0,继续放回map
if (count > 0) {
map.put(nums2[i], count);
} else {
//否则移除
map.remove(nums2[i]);
}
}
}
//拷贝数组
return Arrays.copyOfRange(num, 0, index);
}
方法二:
public int[] intersect(int[] nums1, int[] nums2) {
//方法2:先对数组进行排序,然后用两个指针指向起始位置,比较两个指针指向的数,如果不一样,将小的指针后移,如果相等,放入数组中
//时间复杂度O(mlogm+nlogn) 空间复杂度O(min(m,n))
Arrays.sort(nums1);
Arrays.sort(nums2);
int length1 = nums1.length;
int length2 = nums2.length;
int[] num = new int[Math.min(length1,length2)];
int index = 0,index1 = 0,index2 = 0;
//终止条件为有一个指针超出数组范围
while (index1 < length1 && index2 < length2){
if (nums1[index1] < nums2[index2]){
index1++;
}else if (nums1[index1] > nums2[index2]){
index2++;
}else {
num[index++] = nums1[index1];
index1++;
index2++;
}
}
return Arrays.copyOfRange(num,0,index);
}