题目
给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。
示例:
解法一:先排序再用双指针
我们可以先将数组排好序,然后用双指针来找相同的数,谁小谁就往右移,直到一个数组移到尽头。
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
Arrays.sort(nums1);
Arrays.sort(nums2);
int one = 0,two = 0;//分别表示数组一、二的指针
int head = 0;//要求数组的指针
while(one < nums1.length && two < nums2.length){
if(nums1[one] < nums2[two]){
one++;
}
else if(nums1[one] == nums2[two]){
nums1[head++] = nums1[one];//把该值赋到一中head所指的位置,然后head++
one++;
two++;
}
else{
two++;
}
}
int[] nums = new int[head];//创建对应的数组用来存放并返回交集
for(int i = 0;i<head;i++){
nums[i] = nums1[i];
}
return nums;
}
}
该算法的时间复杂度是sort的时间复杂度O(nlogn),所占空间也仅仅是创建了常数个数组,所以空间复杂度为O(n)。
解法二:使用Map和List解决
关于求两个数组重复的问题,我们自然而然地就会想到Map和Set容器。然而,Set容器只能存放value值,而且还不能相等。那么Map呢?虽然Map中的Key不能相等,但是value可以,那么应该如何合理地使用key和value呢?
我们可以把要存入的元素设置为key值,把该元素的存入个数设置为value值。先遍历nums1,对应的key存入一个,value值+1,再遍历nums2,map中每存在一个,将其放入list容器中,value值-1。最后将list容器转为数组并返回。
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
Map<Integer,Integer> m = new HashMap<>();
List<Integer> l = new ArrayList<>();
//将nums1放入Map中
for(int i = 0;i<nums1.length;i++){
if(m.containsKey(nums1[i])){
m.put(nums1[i],m.get(nums1[i])+1);
}
else{
m.put(nums1[i],1);
}
}
// 判断nums2中的元素Map里面是否存在,存在就放到List里
for(int i = 0;i<nums2.length;i++){
if(m.containsKey(nums2[i]) && m.get(nums2[i])>0){
m.put(nums2[i],m.get(nums2[i])-1);
l.add(nums2[i]);
}
}
// 将l转换为数组
// Integer[] num = l.toArray(new Integer[l.size()]);
int[] nums = new int[l.size()];
for(int i = 0;i<l.size();i++){
nums[i] = l.get(i);
}
return nums;
}
}
注意:对于List容器中存放整型数据,是不能直接使用toArray()方法的,因为容器类型为包装类型Integer,无法之间转换或者是强转为int型,所以要想转为int数组就只能使用for循环遍历实现。