548. 两数组的交集 II
给定两个数组,计算两个数组的交集
样例
样例1
输入:
nums1 = [1, 2, 2, 1], nums2 = [2, 2]
输出:
[2, 2]
样例2
输入:
nums1 = [1, 1, 2], nums2 = [1]
输出:
[1]
挑战
-如果给定的数组已经排序了怎么办?如何优化算法?
-如果nums1的大小比num2的小怎么办?哪种算法更好?
-如果nums2的元素存储在磁盘上,并且内存受到限制,以至于不能一次将所有元素加载到内存中,该怎么办?
注意事项
每个元素出现次数得和在数组里一样
答案可以以任意顺序给出
public class Solution {
/**
* @param nums1: an integer array
* @param nums2: an integer array
* @return: an integer array
*/
public int[] intersection(int[] nums1, int[] nums2) {
ArrayList<Integer> set = new ArrayList<>();
for (int value : nums1) {
set.add(value);
}
set.sort(Integer::compareTo);
ArrayList<Integer> set2 = new ArrayList<>();
for (int value : nums2) {
set2.add(value);
}
set2.sort(Integer::compareTo);
List<Integer> list = new ArrayList<>();
int i = 0;
int j = 0;
while (i <set.size()&&j < set2.size()) {
// System.out.println(""+set.get(i));
if (set.get(i) > set2.get(j)){
j++;
}else if (set.get(i) < set2.get(j)){
i++;
}else{
// System.out.println(""+set.get(i));
list.add(set.get(i));
i++;
j++;
}
}
int[] ret = new int[list.size()];
i = 0;
for (int value : list) {
ret[i] = value;
i++;
}
return ret;
}
}
hashset
解题思路
• 使用两个集合解决这个问题。
• 首先,将nums1中的元素加入到集合set1中。
• 依次检查nums2中的元素是否在set1中,如果在,说明属于交集元素,加入到交集集合set2中。
• 遍历set2,把所有元素加入到数组res中,返回res。
复杂度分析
• 时间复杂度:O(m+n)O(m+n),m和n分别表示nums1和nums2的长度。算法中对nums1和nums2分别进行遍历。
• 空间复杂度: O(max(n,m)O(max(n,m),m表示nums1的长度。集合set1的长度最长为m,set2和res的长度不会超过set1。
双指针
解题思路
• 首先,将nums1和nums2排序。
• 定义双指针i和j,分别指向两个数组。从前向后遍历寻找交集元素。
o 当nums1[i] < nums2[j],i后移1位
o 当nums1[i] > nums2[j],j后移1位
o 当nums1[i] == nums2[j],把nums1[i]加入集合intersect,i后移1位,j后移1位
• 将集合intersect的元素加入res中
复杂度分析
• 时间复杂度:O(mlog(m)+nlog(n))O(mlog(m)+nlog(n)),其中m和n分别是nums1和nums2长度。排序算法的时间复杂度是O(mlog(m)+nlog(n))O(mlog(m)+nlog(n)),双指针扫描的复杂度是O(m+n)O(m+n)。
• 空间复杂度:O(1)O(1),常量空间。
二分查找
解题思路
• 首先,将nums1排序。
• 对于nums2中的每个元素,在有序的nums1中进行二分查找,如果找到,加入intersect集合中。
• 将集合intersect的元素移入res中。
复杂度分析
• 时间复杂度:O(mlogm+nlogm)O(mlogm+nlogm),m和n分别为nums1和nums2的长度。对nums1排序的时间复杂度是O(mlogm)O(mlogm),在nums1中搜索nums2所有元素的时间复杂度为O(nlogm)O(nlogm)
• 空间复杂度:O(1)O(1)。常量空间。
0