349. 两个数组的交集【HashSet(遍历)、双指针--Arrays.copyOfRange(ans, 0, idx);】

这篇博客介绍了如何使用哈希表解决寻找两个整数数组的交集问题。提供了C和Java两种语言的解决方案,包括常规方法和优化方法。C语言的实现包括一个数组哈希和两个数组哈希的版本,而Java代码则展示了常规版和优化版的哈希处理,以及双指针法。优化版通过减少遍历次数提高了效率。
摘要由CSDN通过智能技术生成

349. 两个数组的交集
HashSet常用方法

给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。

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

示例 2:
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的

提示:
1 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 1000


要求元素唯一:用 set 来去重
在这里插入图片描述


C代码:1个数组哈希

int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){
    int arr[1001] = {0};
    for (int i = 0; i < nums1Size; ++i) {
        arr[nums1[i]]++;
    }

    int* ans = (int*)malloc(sizeof(int) * nums1Size);
    int ansTop = 0;
    for (int i = 0; i < nums2Size; ++i) {
        if (arr[nums2[i]] > 0) {
            arr[nums2[i]] = 0;   // 避免重复
            ans[ansTop++] = nums2[i];
        }
    }
    *returnSize = ansTop;
    return ans;
}

C代码:2个数组哈希

// 数组哈希
// for循环遍历

int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){
    int arr1[1001] = {0};
    int arr2[1001] = {0};
    for (int i = 0; i < nums1Size; ++i) {
        arr1[nums1[i]]++;
    }
    for (int i = 0; i < nums2Size; ++i) {
        arr2[nums2[i]]++;
    }
    int len = nums1Size > nums2Size ? nums2Size : nums1Size;
    int* ans = (int*)malloc(sizeof(int) * len);
    int ansTop = 0;
    for (int i = 0; i < 1000; ++i) {
        if (arr1[i] > 0 && arr2[i] > 0) {
            ans[ansTop++] = i;
        }
    }
    *returnSize = ansTop;
    return ans;
}

Java代码1:常规版

先将两个数组,分别放到set1、set2中,再求交集:
遍历set1,判断set1的 “每个元素” 是否在set2中!

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> set1 = new HashSet<Integer>();
        Set<Integer> set2 = new HashSet<Integer>();
        for (int num : nums1) {
            set1.add(num);
        }
        for (int num : nums2) {
            set2.add(num);
        }
        return getIntersection(set1, set2);
    } 
    public int[] getIntersection(Set<Integer> set1, Set<Integer> set2) {
        if (set1.size() > set2.size()) {
            return getIntersection(set2, set1); //剪枝:只是为了确保for each时,遍历最短的set。
        }
        Set<Integer> set3 = new HashSet<Integer>();
        for (int num : set1) {  // 遍历set1
            if (set2.contains(num)) {
                set3.add(num);
            }
        }
        int[] ans = new int[set3.size()];
        int i = 0;
        for (int num : set3) { // 将set中的元素,转移到int[]中
            ans[i++] = num;
        }
        return ans;
    }
}
//执行用时:3 ms, 在所有 Java 提交中击败了30.03%的用户
//内存消耗:41.8 MB, 在所有 Java 提交中击败了5.15%的用户

Java代码2:优化版

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> set1 = new HashSet<Integer>();
        Set<Integer> set2 = new HashSet<Integer>();
        for (int num : nums1) {
            set1.add(num);   // 用于 set1.contains(),遍历nums2
        }
        for (int num : nums2) {
            if (set1.contains(num)) {
                set2.add(num);  // 添加重复元素时,set自动去重
            }
        }
        int[] ans = new int[set2.size()];
        int i = 0;
        for (int num : set2) {
            ans[i++] = num; //将一个类中的集合的元素,放到int[]数组中
        }
        return ans;
    }
}
//执行用时:2 ms, 在所有 Java 提交中击败了95.98%的用户
//内存消耗:41.4 MB, 在所有 Java 提交中击败了61.25%的用户

Java代码3:双指针

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Arrays.sort(nums1);
        Arrays.sort(nums2);
        int len1 = nums1.length, len2 = nums2.length;
        int[] ans = new int[len1 + len2];  // 返回的是int[]类型
        int idx = 0;  // 用于数组idx
        int idx1 = 0, idx2 = 0;  // 双指针
        while (idx1 < len1 && idx2 < len2) {
            int num1 = nums1[idx1], num2 = nums2[idx2];
            if (num1 == num2) {
                if (idx == 0 || num1 != ans[idx-1]) {
                    ans[idx++] = num1;
                }
                ++idx1;
                ++idx2;
            } else if (num1 > num2) {
                ++idx2;
            } else {
                ++idx1;
            }
        }
        return Arrays.copyOfRange(ans, 0, idx);
    }
}
//执行用时:2 ms, 在所有 Java 提交中击败了95.98%的用户
//内存消耗:41.3 MB, 在所有 Java 提交中击败了67.12%的用户
// java 遍历set
 Iterator it = set.iterator();
 while(it.hasNext()){
     int num=(int)it.next();
     ...
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值