LeetCode 349. 两个数组的交集

349. 两个数组的交集

给定两个数组 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

解法1:两个集合

使用哈希集合存储元素,可以在 O(1) 的时间内判断一个元素是否在集合中,从而降低时间复杂度。假设数组 nums1 和 nums2 的长度分别是 m 和 n。

首先使用两个哈希集合分别存储两个数组中的元素,然后遍历较小的集合,判断其中的每个元素是否在另一个集合中,如果元素也在另一个集合中,则将该元素添加到返回值。该方法的时间复杂度为 O(m+n)。

Java版:

int数组转set:
首先使用Arrays.stream(intArray)int数组转换为IntStream,然后使用boxed()方法将IntStream中的int值装箱成Integer对象,最后使用collect(Collectors.toSet())收集成一个Set

set转int数组:

使用Java 8的stream API将Set转换为int数组。可以使用stream()方法将Set转换为流,然后使用mapToInt()方法将流中的元素转换为int类型,最后使用toArray()方法将流中的元素收集到int数组中。

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        // 确保 nums1 是长度较短的数组
        if (nums1.length > nums2.length) {
            intersection(nums2, nums1);
        }
        // int[] -> set
        Set<Integer> set1 = Arrays.stream(nums1).boxed().collect(Collectors.toSet());
        Set<Integer> set2 = Arrays.stream(nums2).boxed().collect(Collectors.toSet());
        ArrayList<Integer> ans = new ArrayList<>();
        for (Integer i : set1) {
            if (set2.contains(i)) {
                ans.add(i);
            }
        }
        // ArrayList -> int[]
        return ans.stream().mapToInt(Integer::intValue).toArray();
    }
}

Python版:

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        if len(nums1) > len(nums2):
            self.intersection(nums2, nums1)

        set1 = set(nums1)
        set2 = set(nums2)
        return [x for x in set1 if x in set2]

复杂度分析

  • 时间复杂度:O(m+n),其中 m 和 n 分别是两个数组的长度。使用两个集合分别存储两个数组中的元素需要 O(m+n) 的时间,遍历较小的集合并判断元素是否在另一个集合中需要 O(min(m,n)) 的时间,因此总时间复杂度是 O(m+n)。
  • 空间复杂度:O(m+n),其中 m 和 n 分别是两个数组的长度。空间复杂度主要取决于两个集合。

解法2: 排序 + 双指针

如果两个数组是有序的,则可以使用双指针的方法得到两个数组的交集。

首先对两个数组进行排序,然后使用两个指针遍历两个数组。可以预见的是加入答案的数组的元素一定是递增的,为了保证加入元素的唯一性,我们需要额外记录变量 pre 表示上一次加入答案数组的元素。

初始时,两个指针分别指向两个数组的头部。每次比较两个指针指向的两个数组中的数字,如果两个数字不相等,则将指向较小数字的指针右移一位,如果两个数字相等,且该数字不等于 pre ,将该数字添加到答案并更新 pre 变量,同时将两个指针都右移一位。当至少有一个指针超出数组范围时,遍历结束。

Java版:

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Arrays.sort(nums1);
        Arrays.sort(nums2);
        int m = nums1.length;
        int n = nums2.length;
        int l = 0;
        int r = 0;
        int[] ans = new int[Math.min(m, n)];
        int i = 0;
        while (l < m && r < n) {
            while (l < m && r < n && nums1[l] == nums2[r]) {
                if (i == 0 || ans[i - 1] != nums1[l]) {
                    ans[i++] = nums1[l];
                }
                l++;
                r++;
            }
            while (l < m && r < n && nums1[l] < nums2[r]) {
                l++;
            }
            while (l < m && r < n && nums2[r] < nums1[l]) {
                r++;
            }
        }
        return Arrays.copyOfRange(ans, 0, i);
    }
}

Python版:

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        nums1.sort()
        nums2.sort()
        m = len(nums1)
        n = len(nums2)
        ans = []
        l, r = 0, 0
        while l < m and r < n:
            while l < m and r < n and nums1[l] == nums2[r]:
                if len(ans) == 0 or ans[-1] != nums1[l]:
                    ans.append(nums1[l])
                l += 1
                r += 1
            while l < m and r < n and nums1[l] < nums2[r]:
                l += 1
            while l < m and r < n and nums2[r] < nums1[l]:
                r += 1
        return ans

复杂度分析

  • 时间复杂度:O(mlogm+nlogn),其中 m 和 n 分别是两个数组的长度。对两个数组排序的时间复杂度分别是 O(mlogm) 和 O(nlogn),双指针寻找交集元素的时间复杂度是 O(m+n),因此总时间复杂度是 O(mlogm+nlogn)。
  • 空间复杂度:O(logm+logn),其中 m 和 n 分别是两个数组的长度。空间复杂度主要取决于排序使用的额外空间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值