LeetCode 350. 两个数组的交集 II ntersection of Two Arrays II
Table of Contents
一、中文版
给定两个数组,编写一个函数来计算它们的交集。
示例 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 即可。