349. Intersection of Two Arrays I &&II (Java)

一、Intersection of Two Arrays I

Given two arrays, write a function to compute their intersection. 
Example: 
    Given nums1 = [1, 2, 2, 1], nums2 = [2, 2], return [2]. 
Note: 
    Each element in the result must be unique. 
The result can be in any order.

不能有重复数字,就想到使用数据类型Set。 
逻辑原理: 

  • 数组一的数据存入hashset 
  • 遍历数组二如果set中存有该数据存入arraylist中,同时从set中remove该元素,防止多个元素重复 
  • 遍历list转变为array返回数据
public class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        if(nums1==null || nums2==null)
            return null;
        if(nums1.length==0 || nums2.length==0)
            return new int[0];

        Set<Integer> set=new HashSet<Integer>();
        for(int i=0;i<nums1.length;i++){
            set.add(nums1[i]);
        }

        List<Integer> res = new ArrayList<Integer>();
        for(int i=0;i<nums2.length;i++){
            if(set.contains(nums2[i])){
                res.add(nums2[i]);
                set.remove(nums2[i]);//!!防止add到重复的数字
            }
        }
        //遍历list成为数组返回
        int[]a=new int[res.size()];
        for(int i=0;i<res.size();i++){
            a[i]=(int)res.get(i);
        }

        return a;
    }
}
PS:  遍历HashSet
Iterator<Integer> i=set.iterator();
while(i.hasNext()){
    int temp=(int)i.next();
}

二、Intersection of Two Arrays II(新增follow up)

Given two arrays, write a function to compute their intersection.

Example:
Given nums1 = [1, 2, 2, 1]nums2 = [2, 2], return [2, 2].

Follow up(答案在后面):

  • What if the given array is already sorted? How would you optimize your algorithm?
  • What if nums1's size is small compared to nums2's size? Which algorithm is better?
  • What if elements of nums2 are stored on disk, and the memory is limited such that you cannot load all elements into the memory at once?

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

三种方法:
  • 按照I的做法
  • 直接使用List,判断List是否contains即可(分析得效率最
  • 两个数组进行排序,使用两个指针求有序数组的交集
假设有k个交叉数,nums1长度n,nums2长度m,maxl=Math.max(n,m);
解法一(类似于I):
    leetcode上用时8ms,时间复杂度O(k*maxl);空间复杂度最大为O(m+n)。
public class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        if(nums1==null || nums2==null || nums1.length==0 || nums2.length==0)
            return new int[]{};
        Map<Integer,Integer> map=new HashMap<Integer,Integer>();
        List<Integer> list=new ArrayList<Integer>();
        
        for(int i=0;i<nums1.length;i++){
            if(map.containsKey(nums1[i])){//containsKey时间复杂度最差为O(map.size());
            	map.put(nums1[i], map.get(nums1[i])+1);
            }else{
            	map.put(nums1[i], 1);
            }
        }
        for(int i=0;i<nums2.length;i++){
        	if(map.containsKey(nums2[i])){
        		list.add(nums2[i]);
        		if(map.get(nums2[i])-1 <= 0){
        			map.remove(nums2[i]);
        		}else{
        			map.put(nums2[i], map.get(nums2[i])-1);
        		}
        	}
        }
        int[]res=new int[list.size()];
        for(int i=0;i<res.length;i++){
        	res[i]=list.get(i);
        }
        return res;
    }
}
 

解法(直接使用List):
    用时16ms,时间复杂度高O(mn),空间复杂度最大为O(m+n)。 最不合适的方法
public class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
    	List<Integer> temp=new ArrayList<Integer>();
        List<Integer> list=new ArrayList<Integer>();
        
        for(int x:nums1){
        	temp.add(x);
        }
        for(int x:nums2){
        	if(temp.contains(x)){//看源码可知contains的复杂度是O(temp.size())
        		list.add(x);
        		temp.remove((Integer)x);
        	}
        }
        int[]res=new int[list.size()];
        for(int i=0;i<res.length;i++){
        	res[i]=list.get(i);
        }
        return res;
    }
}

解法三(数组排序,两个指针):
    用时5ms,时间复杂度O(maxl*log(maxl)),空间复杂度为O(k)
public class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        Arrays.sort(nums1);//底层使用了快排,O(nlogn)
        Arrays.sort(nums2);
        List<Integer> list=new ArrayList<Integer>();
        for(int i=0,j=0;i<nums1.length&&j<nums2.length;){
        	if(nums1[i]==nums2[j]){ 
        		list.add(nums1[i]);
        		i++;
        		j++;
        	}
        	else if(nums1[i]>nums2[j]){
        		j++;
        	}else{
        		i++;
        	}
        }
        int[]res=new int[list.size()];
        for(int i=0;i<res.length;i++){
        	res[i]=list.get(i);
        }
        return res;
    }
}

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

问题

  • What if the given array is already sorted? How would you optimize your algorithm?(第三种最好,且无须排序)
  • What if nums1's size is small compared to nums2's size? Which algorithm is better?(第一种比较好,nums1用hash表)
  • What if elements of nums2 are stored on disk, and the memory is limited such that you cannot load all elements into the memory at once?(如果能放下nums1就使用第一种,做成hash表;如果两个数组都放不下,就外部排序然后使用第三种)



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值