LeetCode 350. 两个数组的交集 II ntersection of Two Arrays II

简介: LeetCode 350. 两个数组的交集 II ntersection of Two Arrays II

LeetCode 350. 两个数组的交集 II ntersection of Two Arrays II


Table of Contents

 

一、中文版

二、英文版

三、My answer

四、解题报告


一、中文版

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

示例 1:

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

输出: [2,2]

示例 2:

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

输出: [4,9]

说明:

输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。

我们可以不考虑输出结果的顺序。

进阶:

如果给定的数组已经排好序呢?你将如何优化你的算法?

如果 nums1 的大小比 nums2 小很多,哪种方法更优?

如果 nums2 的元素存储在磁盘上,磁盘内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?


二、英文版

Given two arrays, write a function to compute their intersection.
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]
Note:
Each element in the result should appear as many times as it shows in both arrays.
The result can be in any order.
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?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/intersection-of-two-arrays-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


三、My answer

class Solution:
    def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
#         version 1:好写,但时间复杂度高 O(n^2)
        # res = []
        for num in nums1:
            # if nums2 is None:
            if not nums2:
                return res
            elif num in nums2:
                res.append(num)
                nums2.remove(num)
        return res
#     version 2: 两个dictionary,
        dict1 = {}
        dict2 = {}
        res = []
        for num in nums1:
            if num in dict1:
                dict1[num] += 1
            else:
                dict1[num] = 1
        for num in nums2:
            if num in dict2:
                dict2[num] += 1
            else:
                dict2[num] = 1
        for key in dict1:
            if key in dict2:
                res = res + [key] * min(dict1[key],dict2[key])
        return res
#     version 3: 一个dictionary
        _dict = {}
        res = []
        for num in nums1:
            if num in _dict:
                _dict[num] += 1
            else:
                _dict[num] = 1
        for num in nums2:
            if num in _dict and _dict[num] >= 1:
                _dict[num] -= 1
                res.append(num)
        return res
#     version 4:双指针
        i = 0
        j = 0
        m = len(nums1)
        n = len(nums2)
        res = []
        nums1.sort()
        nums2.sort()
        while i < m and j < n:
            while i < m and j < n and nums1[i] < nums2[j]:
                i += 1
            while i < m and j < n and nums1[i] > nums2[j]:
                j += 1
            if i < m and j < n and nums1[i] == nums2[j]:
                res.append(nums1[i])
                i += 1
                j += 1
        return res
#     version 5: version 4 的清晰版
        i = 0
        j = 0
        m = len(nums1)
        n = len(nums2)
        res = []
        nums1.sort()
        nums2.sort()
        while i < m and j < n:
            if nums1[i] < nums2[j]:
                i += 1
            elif nums1[i] > nums2[j]:
                j += 1
            else:
                res.append(nums1[i])
                i += 1
                j += 1
        return res


四、解题报告

version 1:遍历 nums1 中的数字,判断其是否在 nums2 中,如果存在,即是两个数组的交集,放入 res 中并在 nums2 中删除该数字以免重复查找。时间复杂度:外层 for 循环是 O(n),内层 remove() 是 O(n),所以总时间复杂度是 O(n^2)。

version 2:使用两个字典,分别记录 nums1 nums2 中数字出现的个数。遍历 dict1 的 key,如果 dict2 中也有,则取两个value的最小值,及一个 num 在两个 nums 中出现的个数,也就是在交集中的个数。时间复杂度 O(n),空间复杂度 O(n)。

version 3:version 2 的简化版,只使用一个字典。将 nums1 的数字整理放入字典中,key 是 num,value 是出现的个数。再遍历 nums2 中的数,如果该数在 字典中有且个数 >= 1,则放入 res 中并将个数 -1。如果个数为 0  表示 nums1 中已经没有该数,不再属于交集。时间复杂度 O(n),空间复杂度 O(n)。

version 4:双指针。两个数组排序后,用两个指针分别遍历两个数组,对所指向数字比较大小。如果相等则属于交集,否则谁小就移动谁,直到相等。时间复杂度 O(nlogn):由于排序的时间复杂度为 O(nlogn),遍历的时间复杂度为 O(n),所以整体时间复杂度为 O(nlogn)。空间复杂度 O(1)。

version 5:version 4 的清晰版,while 改成  if 即可。

相关文章
|
1月前
|
算法
Leetcode 初级算法 --- 数组篇
Leetcode 初级算法 --- 数组篇
38 0
|
3月前
|
算法
LeetCode第53题最大子数组和
LeetCode第53题"最大子数组和"的解题方法,利用动态规划思想,通过一次遍历数组,维护到当前元素为止的最大子数组和,有效避免了复杂度更高的暴力解法。
LeetCode第53题最大子数组和
|
1月前
【LeetCode-每日一题】 删除排序数组中的重复项
【LeetCode-每日一题】 删除排序数组中的重复项
19 4
|
1月前
|
索引
Leetcode第三十三题(搜索旋转排序数组)
这篇文章介绍了解决LeetCode第33题“搜索旋转排序数组”的方法,该问题要求在旋转过的升序数组中找到给定目标值的索引,如果存在则返回索引,否则返回-1,文章提供了一个时间复杂度为O(logn)的二分搜索算法实现。
18 0
Leetcode第三十三题(搜索旋转排序数组)
|
1月前
|
算法 C++
Leetcode第53题(最大子数组和)
这篇文章介绍了LeetCode第53题“最大子数组和”的动态规划解法,提供了详细的状态转移方程和C++代码实现,并讨论了其他算法如贪心、分治、改进动态规划和分块累计法。
56 0
|
1月前
|
C++
【LeetCode 12】349.两个数组的交集
【LeetCode 12】349.两个数组的交集
16 0
|
3月前
|
算法
LeetCode第81题搜索旋转排序数组 II
文章讲解了LeetCode第81题"搜索旋转排序数组 II"的解法,通过二分查找算法并加入去重逻辑来解决在旋转且含有重复元素的数组中搜索特定值的问题。
LeetCode第81题搜索旋转排序数组 II
|
2月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
56 6
|
3月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
113 2