题目
给定两个数组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,将所有元素添加到哈希表中。
2、查找交集。遍历第二个数组nums2,检查每个元素是否在哈希表中。
3、收集结果。如果元素存在于哈希表中,则将其添加到结果列表中。同时,从哈希表中移除该元素,以避免重复添加。
4、返回收集到的结果列表。
根据上面的算法步骤,我们可以得出下面的示例代码。
def array_intersection_by_hash(nums1, nums2):
result = []
# 使用集合存储nums1中的元素
hash_set = set(nums1)
# 遍历nums2中的每个元素
for num in nums2:
# 如果元素存在于哈希表中
if num in hash_set:
# 添加到结果列表中
result.append(num)
# 从哈希表中移除该元素,以避免重复
hash_set.remove(num)
return result
nums1 = [1, 2, 2, 1]
nums2 = [2, 2]
print(array_intersection_by_hash(nums1, nums2))
nums1 = [4, 9, 5]
nums2 = [9, 4, 9, 8, 4]
print(array_intersection_by_hash(nums1, nums2))
双指针法
使用双指针法求解两个数组的交集也是一种效率较高的方法,尤其是在两个数组都已经排序的情况下。对于两个已排序的数组,可以通过双指针法找到它们的交集。这种方法的核心是:同时维护两个指针,一个指向第一个数组中的元素,另一个指向第二个数组中的元素。通过比较这两个指针所指向的元素值,可以有效地找到交集中的元素。使用双指针法求解本题的主要步骤如下。
1、排序数组。如果输入数组未排序,则先对两个数组进行排序。
2、分别为两个数组初始化指针i和j。
3、比较元素。比较两个指针所指向的元素,进行以下操作。
(1)如果两个元素相等,且该元素不同于上一个加入结果集的元素,则加入结果集。
(2)如果nums1[i] < nums2[j],则移动nums1的指针i。
(3)如果nums1[i] > nums2[j],则移动nums2的指针j。
4、继续遍历。重复步骤3,直到遍历完任一阵列。
5、返回收集到的结果列表。
根据上面的算法步骤,我们可以得出下面的示例代码。
def array_intersection_by_two_pointers(nums1, nums2):
result = []
# 先对两个数组进行排序
nums1.sort()
nums2.sort()
# 初始化两个指针
i, j = 0, 0
# 用于记录上一个加入结果集的元素
prev = None
# 遍历两个数组直到有一个数组遍历结束
while i < len(nums1) and j < len(nums2):
if nums1[i] == nums2[j]:
# 如果当前元素与上一个加入结果集的元素不同,则加入结果集
if nums1[i] != prev:
result.append(nums1[i])
prev = nums1[i]
# 移动两个指针
i += 1
j += 1
elif nums1[i] < nums2[j]:
# 移动nums1的指针
i += 1
else:
# 移动nums2的指针
j += 1
return result
nums1 = [1, 2, 2, 1]
nums2 = [2, 2]
print(array_intersection_by_two_pointers(nums1, nums2))
nums1 = [4, 9, 5]
nums2 = [9, 4, 9, 8, 4]
print(array_intersection_by_two_pointers(nums1, nums2))
内置函数
实际上,我们还可以使用Python的内置函数来求解本题。其原理与上面介绍的哈希法基本类似,这里就不再赘述了。使用内置函数求解本题的示例代码如下。
def array_intersection_by_builtin_func(nums1, nums2):
return list(set(nums1) & set(nums2))
nums1 = [1, 2, 2, 1]
nums2 = [2, 2]
print(array_intersection_by_builtin_func(nums1, nums2))
nums1 = [4, 9, 5]
nums2 = [9, 4, 9, 8, 4]
print(array_intersection_by_builtin_func(nums1, nums2))
总结
使用哈希法求解本题时,构建哈希表的时间复杂度为O(n),遍历查找的时间复杂度为O(m),故总体时间复杂度为O(n + m)。其中,n是nums1的长度,m是nums2的长度。哈希法的优点是实现简单,且不依赖于输入数组是否有序。
使用双指针法求解本题时,排序的时间复杂度为O(nlogn) + O(mlogm),双指针遍历的时间复杂度为O(n + m),故总体时间复杂度为O(nlogn + mlogm)。对于排序后的数组,可以直接使用双指针法进行高效的查找。但其实现稍微复杂一些,需要考虑边界条件等各自情况。