题干要求
给定两个整数数组 nums1 和 nums2,返回它们的交集。输出结果中的每个元素一定是唯一的,不考虑输出结果的顺序。
二、两种核心解法(面试高频,直接 AC)
解法 1:HashSet 最优解(推荐!线性时间,新手首选)
核心思路
利用 HashSet「自动去重」和「O (1) 快速查找」的特性:
- 把其中一个数组存入 HashSet(自动去重,减少查找次数);
- 遍历另一个数组,判断元素是否在 HashSet 中存在;
- 用另一个 HashSet 存储结果(避免遍历数组时出现重复元素);
- 最后将结果 HashSet 转为数组。
代码实现:
java
import java.util.HashSet;
import java.util.Set;
public class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
// 用HashSet存nums1,自动去重
Set<Integer> set = new HashSet<>();
for (int num : nums1) {
set.add(num);
}
// 存结果,避免重复
Set<Integer> resSet = new HashSet<>();
for (int num : nums2) {
// 存在即交集元素
if (set.contains(num)) {
resSet.add(num);
}
}
// Set转数组,简洁写法
return resSet.stream().mapToInt(Integer::intValue).toArray();
}
}
复杂度分析
- 时间:O (m + n)(m、n 为数组长度,两次线性遍历,查找是 O (1));
- 空间:O (min (m, n))(仅存储较短数组的元素,优化空间)
解法 2:排序 + 双指针(省空间,适配空间限制场景)
核心思路
- 两个数组先排序,利用排序后元素有序的特性;
- 双指针分别从数组开头出发,对比元素:
- 元素相等 → 加入结果(需跳过后续重复元素,保证唯一);
- 元素不等 → 小的指针后移(有序数组中,小元素不可能是交集)。
代码实现
java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
// 排序预处理
Arrays.sort(nums1);
Arrays.sort(nums2);
int i = 0, j = 0;
List<Integer> resList = new ArrayList<>();
while (i < nums1.length && j < nums2.length) {
if (nums1[i] == nums2[j]) {
// 加入结果,同时跳过重复元素(保证唯一)
resList.add(nums1[i]);
// 跳过nums1的重复元素
while (i < nums1.length - 1 && nums1[i] == nums1[i + 1]) {
i++;
}
// 跳过nums2的重复元素
while (j < nums2.length - 1 && nums2[j] == nums2[j + 1]) {
j++;
}
// 双指针同时后移
i++;
j++;
} else if (nums1[i] < nums2[j]) {
i++;
} else {
j++;
}
}
// List转数组
return resList.stream().mapToInt(Integer::intValue).toArray();
}
}
复杂度分析
- 时间:O (m logm + n logn)(排序占主要耗时,双指针遍历是 O (m + n));
- 空间:O (1)(忽略排序系统栈空间,仅用 List 存结果,题目不计数组输出空间)。
总结
这道题的核心是「去重 + 找共同元素」,两种解法覆盖不同场景,新手优先掌握 HashSet 解法(易理解、易实现),再进阶学习双指针思路。