两个数组的交集

Posted KeepGoing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了两个数组的交集相关的知识,希望对你有一定的参考价值。

1.问题描述

给定两个数组,编写一个函数来计算它们的交集。

示例 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 的元素存储在磁盘上,内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?

2.求解

哈希表

  • 比较两个数组的长度,遍历较大的数组,将其存入元素作为键,出现次数作为值,存入hash表中
  • 遍历另一个较小的数组,若它的元素在哈希表中出现,即把其存入新的数组中,并且将出现次数减一,重新存入哈希表中

代码如下

/*
* 执行用时:4 ms, 在所有 Java 提交中击败了53.75% 的用户
* 内存消耗:38.9 MB, 在所有 Java 提交中击败了51.97% 的用户
* */
public int[] intersect(int[] nums1, int[] nums2) {
    if(nums2.length > nums1.length){
        return intersect(nums2,nums1);
    }
    Map<Integer, Integer> map = new HashMap<>();
    for(int num : nums1){
        map.merge(num, 1, (oldX, newX) -> oldX += 1);
    }
    int[] res = new int[nums1.length];
    int index = 0;
    for(int num : nums2){
        int count = map.getOrDefault(num, 0);
        if(count > 0){
            res[index] = num;
            index ++;
            count --;
        }
        map.put(num, count);
    }
    return Arrays.copyOfRange(res, 0, index);
}
  • 时间复杂度:O(n),n为两数组大小之和
  • 空间复杂度:O(n),n为较小数组元素个数

ps:对int[]数组的复制操作

  • System.arraycopy(arr, copied, start, end);

  • Arrays.copyOfRange(intersection, 0, index);

    区别:Arrays.copyOf()不仅仅只是拷贝数组中的元素,在拷贝元素时,会创建一个新的数组对象。而System.arrayCopy只拷贝已经存在数组元素。

    ? Array.copyOf()底层是调用的System.arrayCopy(new了一个数组对象,复制后返回)

排序 + 双指针

代码如下

    /*
     *执行用时:1 ms, 在所有 Java 提交中击败了100.00% 的用户
     *内存消耗:38.8 MB, 在所有 Java 提交中击败了75.93% 的用户
     */
	public int[] intersect(int[] nums1, int[] nums2) {
        Arrays.sort(nums1);
        Arrays.sort(nums2);
        int m = nums1.length;
        int n = nums2.length;
        int[] res = new int[m + n];
        int length = 0;
        int i = 0, j = 0;
        while(i < m && j < n){
            if(nums1[i] == nums2[j]){
                res[length] = nums1[i];
                length++;
                i++;
                j++;
            }else if(nums1[i] < nums2[j]){
                i++;
            }else{
                j++;
            }
        }
        return Arrays.copyOfRange(res, 0, length);
    }
  • 时间复杂度:O(mlog?m+nlog?n),排序的时间复杂度是O(mlog?m+nlog?n),遍历的时间复杂度是O(m + n),所以总的时间复杂度是O(mlogm + nlogn)
  • 空间复杂度:O(m +n)

ps:这里新建数组可以改成如下。

? int[] res = new int[Math.min(m,n)],这样空间复杂度就变成了O(min(m,n))

以上是关于两个数组的交集的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 349. 两个数组的交集

LC 两个数组的交集 II

c语言求两个数组的并交集

两个字符串数组的快速 count() 交集

PHP 两个二维数组求交集

349哈希表-两个数组的交集