1.如果两个数组有序的话,那么必然采用方法二
2.如果两个数组的大小差距很大采用方法一,首先将小的放入HashMap这样会节约Map的空间,其次如果一个
数组过大的话,进行排序NlogN的时间太大
3.如果 nums2 的元素存储在磁盘上,磁盘内存是有限的,并且你不能一次加载所有的元素到内存中,那么必然
不能采用费内存的方法一,要先在外部进行排序再读取两个文件
方法一:利用HashMap实现计数
- 时间复杂度O(N+M),N是nums1的长度,M是nums2的长度
- 空间复杂度是 O(Math.min(N,M)),两个数组的交集最大就是最小值
public int[] intersect(int[] nums1, int[] nums2) {
if (nums1.length > nums2.length) {
return intersect(nums2, nums1);
}
HashMap<Integer, Integer> m = new HashMap<>();
for (int n : nums1) {
m.put(n, m.getOrDefault(n, 0) + 1);
}
int k = 0;
for (int n : nums2) {
int cnt = m.getOrDefault(n, 0);
if (cnt > 0) {
nums1[k++] = n;
m.put(n, cnt - 1);
}
}
return Arrays.copyOfRange(nums1, 0, k);
}
方法二:双指针
- 时间复杂度首选是两个数组的排序,一个是O(NlogN),一个是O(MlogM),遍历的时间复杂度是N+M
这样的话就是三者的一个最大值,就和具体的N和M有关系了 - 空间复杂度是O(1),不需要额外的空间
public int[] intersect(int[] nums1, int[] nums2) {
Arrays.sort(nums1);
Arrays.sort(nums2);
LinkedList<Integer> list=new LinkedList<>();
int p1=0,p2=0;
while(p1<nums1.length && p2<nums2.length)
{
if(nums1[p1]<nums2[p2]) p1++;
else if(nums1[p1]>nums2[p2]) p2++;
else{
list.add(nums1[p1]);
p1++;
p2++;
}
}
int res[]=new int[list.size()];
int index=0;
for(int i:list) res[index++]=i;
return res;
}