leetcode 刷题(84)——350.两个数组的交集 II

本文介绍了两种计算两个数组交集的有效方法:哈希映射和排序。哈希映射通过统计一个数组中每个数字出现的次数,使用HashMap存储,再遍历另一个数组,查找并减少次数来获取交集。排序方法则是先对两个数组进行排序,然后通过比较和移动指针的方式找出重复元素。

一、题目

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

示例 1:

输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2,2]

示例 2:

输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出: [4,9]

说明:

  • 输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。
  • 我们可以不考虑输出结果的顺序。

二、思路及代码实现

思路一:哈希映射

  • 统计一个数组中每个数字出现的次数,存放在 HashMap 中(以 值-出现次数 的形式存储);
  • 遍历另一个数组,查找每个数字是否存在哈希表中,如果存在,将该数字添加至结果集,并把 hashMap 中对应的次数减一;如果不存在,则检查下一个数字。

代码实现(一):

class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        Map<Integer, Integer> map = new HashMap<>();
        for(int i : nums1){
            if(map.containsKey(i))
                map.put(i, map.get(i) + 1);
            else
                map.put(i, 1);
        }
        int k = 0;
        for(int n : nums2){
            if(map.containsKey(n) && map.get(n) > 0){
                nums1[k++] = n;
                map.put(n, map.get(n) - 1);
            }
        }
        return Arrays.copyOfRange(nums1, 0, k);
    }
}

利用 Map 的 getOrDefault() 方法,可以简化代码。

Map 的 getOrDefault(key, defaultValue) 方法:

  • 括号中的第一个参数是你要取的 key,第二个参数是你指定的默认值;
  • 意思是:如果 map 中存在 key 这个键,那就返回这个键对应的值;不存在这个 key,则返回默认值。

举个例子:

Map<Integer, Integer> map = new HashMap<>();
map.put(1, 11);

// 存在 1 这个键,返回其对应的值 11
System.out.println(map.getOrDefault(1, 22)); // 11
// 不存在 3 这个键,返回默认值 33
System.out.println(map.getOrDefault(3, 33)); // 33

// 需要注意的是:
// 		只要存在这个 key,就返回它对应的值,即使这个值为 null;不存在这个 key 时,才返回默认值。
map.put(4, null);
// 这里打印的是 null,而不是 22
System.out.println(map.getOrDefault(4, 22));

简化代码如下:

class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        Map<Integer, Integer> map = new HashMap<>();
        for(int i : nums1){
            int count = map.getOrDefault(i, 0);
            map.put(i, count + 1);
        }
        int k = 0;
        for(int n : nums2){
            int t = map.getOrDefault(n, 0);
            if(t > 0){
                nums1[k++] = n;
                map.put(n, t - 1);
            }
        }
        return Arrays.copyOfRange(nums1, 0, k);
    }
}

思路二:排序

分别对两个数组进行排序,然后逐个比对两个数组的元素,找到重复元素。

  • 对两个数组排序;
  • 初始化三个指针 i = 0、j = 0、k = 0,i 和 j 指向两个数组,k 用来记录重复元素的个数;
    • 如果 nums1[i]=nums2[j]nums1[i] = nums2[j]nums1[i]=nums2[j],将该元素拷贝到 nums1[k]nums1[k]nums1[k],然后 i++,j++,k++;
    • 如果 nums1[i]>nums2[j]nums1[i] > nums2[j]nums1[i]>nums2[j],j++;
    • 如果 nums1[i]<nums2[j]nums1[i] < nums2[j]nums1[i]<nums2[j],i++。
  • 最后返回 nums1 的前 k 个元素。

代码如下:

class Solution {
    public int[] intersect(int[] nums1, int[] nums2){
        Arrays.sort(nums1);
        Arrays.sort(nums2);
        int i = 0, j = 0, k = 0;
        while(i < nums1.length && j < nums2.length){
            if(nums1[i] == nums2[j]){
                nums1[k] = nums2[j];
                i++;
                j++;
                k++;
            }else if(nums1[i] > nums2[j]){
                j++;
            }else if(nums1[i] < nums2[j]){
                i++;
            }
        }
        return Arrays.copyOfRange(nums1, 0, k);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值