力扣349. 两个数组的交集

题干要求

给定两个整数数组 nums1nums2,返回它们的交集。输出结果中的每个元素一定是唯一的,不考虑输出结果的顺序。

二、两种核心解法(面试高频,直接 AC)

解法 1:HashSet 最优解(推荐!线性时间,新手首选)

核心思路

利用 HashSet「自动去重」和「O (1) 快速查找」的特性:

  1. 把其中一个数组存入 HashSet(自动去重,减少查找次数);
  2. 遍历另一个数组,判断元素是否在 HashSet 中存在;
  3. 用另一个 HashSet 存储结果(避免遍历数组时出现重复元素);
  4. 最后将结果 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:排序 + 双指针(省空间,适配空间限制场景)

核心思路
  1. 两个数组先排序,利用排序后元素有序的特性;
  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 解法(易理解、易实现),再进阶学习双指针思路。

相关推荐
_OP_CHEN8 小时前
【算法基础篇】(五十七)线性代数之矩阵乘法从入门到实战:手撕模板 + 真题详解
线性代数·算法·矩阵·蓝桥杯·c/c++·矩阵乘法·acm/icpc
天天爱吃肉82188 小时前
【跨界封神|周杰伦×王传福(陶晶莹主持):音乐创作与新能源NVH测试,底层逻辑竟完全同源!(新人必看入行指南)】
python·嵌入式硬件·算法·汽车
im_AMBER8 小时前
Leetcode 114 链表中的下一个更大节点 | 删除排序链表中的重复元素 II
算法·leetcode
xhbaitxl8 小时前
算法学习day38-动态规划
学习·算法·动态规划
多恩Stone8 小时前
【3D AICG 系列-6】OmniPart 训练流程梳理
人工智能·pytorch·算法·3d·aigc
历程里程碑8 小时前
普通数组----轮转数组
java·数据结构·c++·算法·spring·leetcode·eclipse
pp起床8 小时前
贪心算法 | part02
算法·leetcode·贪心算法
sin_hielo8 小时前
leetcode 1653
数据结构·算法·leetcode
2501_901147838 小时前
面试必看:优势洗牌
笔记·学习·算法·面试·职场和发展
李日灐8 小时前
C++进阶必备:红黑树从 0 到 1: 手撕底层,带你搞懂平衡二叉树的平衡逻辑与黑高检验
开发语言·数据结构·c++·后端·面试·红黑树·自平衡二叉搜索树