每日一题:两个数组的交集||

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情 

题目链接

给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。

示例 1:

输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2,2]
复制代码

示例 2:

输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出: [4,9]
复制代码

  提示:

  • 1 <= nums1.length, nums2.length <= 1000
  • 0 <= nums1[i], nums2[i] <= 1000

解题思路:(哈希表)

这道题和我之前写过的一道题类似,感兴趣的可以先将那道题一做,再来做这道题,两个数组的交集|

因为这道题中并没有要求数组里的元素不重复,这意味着一个元素可能在数组中出现多次,我们就需要使用哈希表来记录元素在数组中出现的次数交集中的某个元素出现的次数应该是它在两个数组中出现次数的最小值

又因为两个数组的交集的长度一定不会超过其中较短的数组的长度,因此我们先遍历较短的数组,并在哈希表中记录每个元素和元素出现的次数

具体思路:

  1. 先比较两条数组的长度,找出较短的数组 nums1
  2. 遍历nums1,并在哈希表中记录下每个元素的值和出现的次数
  3. 创建一个新的数组,作为结果返回,数组的长度就是nums1的长度
  4. 再遍历另一个数组nums2,对于nums2中的每一个元素,如果在哈希表中可以找到,就将元素添加到结果数组中,并且减少哈希表中这个元素出现的次数

代码:(JAVA实现)

public int[] intersect(int[] nums1, int[] nums2) {
        if (nums1.length > nums2.length) {
            return intersect(nums2,nums1);
        }
        HashMap<Integer,Integer> hashmap = new HashMap<>();
        for (int i : nums1) {
            //这里的count就是每个元素出现的次数,后面的+1是为了保证添加进哈希表的元素至少有一次
            int count = hashmap.getOrDefault(i,0)+1;
            hashmap.put(i,count);
        }

        int[] nums = new int[nums1.length];
        //记录结果数组元素的个数
        int index = 0;
        for (int i : nums2) {
            int count = hashmap.getOrDefault(i,0);
            if (count > 0) {
                nums[index] = i;
                index++;
                count--;
                if (count > 0) {
                    hashmap.put(i,count);
                }else {
                    hashmap.remove(i);
                }
            }
        }
       
        return Arrays.copyOfRange(nums,0,index);
复制代码

复杂度分析

  • 时间复杂度:O(M+N),其中 m 和 n 分别是两个数组的长度。需要遍历两个数组并对哈希表进行操作,哈希表操作的时间复杂度是 O(1),因此总时间复杂度与两个数组的长度和呈线性关系。
  • 空间复杂度:O(min(M,N)),其中 m 和 n 分别是两个数组的长度。对较短的数组进行哈希表的操作,哈希表的大小不会超过较短的数组的长度。为返回值创建一个数组 nums,其长度为较短的数组的长度。

提交结果

image.png

解题思路: (排序+双指针)

如果两个数组是有序的,我们就可以通过双指针来遍历来得到数组的交集

具体思路:

  1. 先对两个数组排序,再使用双指针进行遍历
  2. 开始时,两个指针分别指向两个数组的开头,比较指针指向的元素是否相等,如果两个指针相等,元素添加到结果数组中,数组同时向后移动一位,如果不相等,把元素较小的那个指针向后移动一位,当至少有一个指针超出了数组的范围,遍历结束

代码:(JAVA实现)

public static int[] intersect(int[] nums1,int[] nums2) {
    Arrays.sort(nums1);
    Arrays.sort(nums2);
    int l1 = nums1.length;
    int l2 = nums2.length;

    int[] ints = new int[Math.min(l1,l2)];

    int nums1_index = 0;
    int nums2_index = 0;
    int ints_index = 0;

    while (nums1_index < l1 && nums2_index < l2) {
        if (nums1[nums1_index] < nums2[nums2_index]) {
            nums1_index++;
        }else if (nums1[nums1_index] > nums2[nums2_index]) {
            nums2_index++;
        }else {
            ints[ints_index++] = nums2[nums2_index];
            nums1_index++;
            nums2_index++;
        }
    }

    return Arrays.copyOfRange(ints,0,ints_index);
}
复制代码

复杂度分析:

  • 时间复杂度:O(mlogm+nlogn)
  • 空间复杂度:O(min(m,n)),其中 m 和 n 分别是两个数组的长度。为返回值创建一个数组 ints,其长度为较短的数组的长度

提交结果

image.png

猜你喜欢

转载自juejin.im/post/7084920623515828254