《中英双解》leetCode 350 Intersection of Two Arrays II(两个数组的交集2)

Given two integer arrays nums1 and nums2, return an array of their intersection. Each element iusn the result mt appear as many times as it shows in both arrays and you may return the result in any order.

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

Example 1:

Input: nums1 = [1,2,2,1], nums2 = [2,2]
Output: [2,2]

Example 2:

Input: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
Output: [4,9]
Explanation: [9,4] is also accepted.

Constraints:

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

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?

这一题有两种解法,一个是排序遍历,一个是用哈希表,我们依次来看看

遍历的时候我们需要申请一个新的数组,这个时候需要注意的是规定数组的大学,大家可以想一下,如果有重复元素的话肯定不会超过最小数组的大小,所以我们可以指定最小数组的大小作为新数组的大小,然后将两个数组排序,再之后我们就依次进行遍历比较,现在看看代码

class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        int length1 = nums1.length;
        int length2 = nums2.length;
        Arrays.sort(nums1);
        Arrays.sort(nums2);
        int length = Math.min(length1,length2);
        int[] array = new int[length];
        int index1 = 0;
        int index2 = 0;
        int index = 0;
        while(index1 < length1 && index2 < length2){
            if(nums1[index1] < nums2[index2]){
                index1++;
            } else if(nums1[index1] > nums2[index2]){
                index2++;
            } else {
                array[index] = nums1[index1];
                index1++;
                index2++;
                index++;
            }
        }
        return Arrays.copyOfRange(array, 0, index);
    }
}

 这里需要注意的是不能直接返回数组,因为你新数组中的元素可能小于数组的大小,这个时候就需要补零,所以要用Arrays.copyOfRange()函数进行数组的截取。

下面看看哈希表的思路。

由于同一个数字在两个数组中都可能出现多次,因此需要用哈希表存储每个数字出现的次数。对于一个数字,其在交集中出现的次数等于该数字在两个数组中出现次数的最小值。

首先遍历第一个数组,并在哈希表中记录第一个数组中的每个数字以及对应出现的次数,然后遍历第二个数组,对于第二个数组中的每个数字,如果在哈希表中存在这个数字,则将该数字添加到答案,并减少哈希表中该数字出现的次数。

为了降低空间复杂度,首先遍历较短的数组并在哈希表中记录每个数字以及对应出现的次数,然后遍历较长的数组得到交集。

class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        if (nums1.length > nums2.length) {
            return intersect(nums2, nums1);
        }
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        for (int num : nums1) {
            int count = map.getOrDefault(num, 0) + 1;
            map.put(num, count);
        }
        int[] intersection = new int[nums1.length];
        int index = 0;
        for (int num : nums2) {
            int count = map.getOrDefault(num, 0);
            if (count > 0) {
                intersection[index++] = num;
                count--;
                if (count > 0) {
                    map.put(num, count);
                } else {
                    map.remove(num);
                }
            }
        }
        return Arrays.copyOfRange(intersection, 0, index);
    }
}

复杂度分析

时间复杂度:O(m+n)O(m+n),其中 mm 和 nn 分别是两个数组的长度。需要遍历两个数组并对哈希表进行操作,哈希表操作的时间复杂度是 O(1)O(1),因此总时间复杂度与两个数组的长度和呈线性关系。

空间复杂度:O(\min(m,n))O(min(m,n)),其中 mm 和 nn 分别是两个数组的长度。对较短的数组进行哈希表的操作,哈希表的大小不会超过较短的数组的长度。为返回值创建一个数组 intersection,其长度为较短的数组的长度。

Map.getOrDefault(Object key, V defaultValue)方法的作用是:
  (1)当Map集合中存在这个key时,就使用这个key值,(若是数值型可以在此基础上进行运算)
  (2)如果没有就使用默认值defaultValue

代码演示1(使用前):

        String t="ABC"
        char ch[] = t.toCharArray();
        List<Character> list = new ArrayList<>();
        //将A中的每个值传入list
        //我是为了后面做题才这么写的,当时想的有点复杂
        for (int k = 0; k < t.length; k++) {
            list.add(ch[k]);
        }
        //-------------正式开始-------------
        HashMap<Character, Integer> map = new HashMap();
        //先将每个key的value赋值为0,因为不赋初值直接计算会报该空指针异常
        for (int k = 0; k < lists.size(); k++) {
            map.put(list.get(k), 0);
        }
           //逐个进行计算
        for (int k = 0; k < lists.size(); k++) {
            map.put(list.get(k), map1.get(list.get(k)) + 1);
        }


代码演示2(使用后):

       String t="ABC"
       Map<Character, Integer> map = new HashMap<>();
       //遍历字符串 t,初始化每个字母的次数
       for (int i = 0; i < t.length(); i++) {
           char chat= t.charAt(i);
           map.put(chat, map.getOrDefault(chat, 0) + 1);
       }


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值