[LeetCode] 349. 两个数组的交集

1. 问题描述

349. 两个数组的交集

给定两个数组 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.length, nums2.length <= 1000
  • 0 <= nums1[i], nums2[i] <= 1000

2. 实现思路

2.1 自己的思路

~~(一定要写出来啊喂)~

有点偏暴力的解法,HashSet有个作用是去重,那么先对两个数组去重,然后利用Contain方法找交集即可

/*
 * @lc app=leetcode.cn id=349 lang=csharp
 *
 * [349] 两个数组的交集
 */

// @lc code=start
public class Solution {
    public int[] Intersection(int[] nums1, int[] nums2)
    {
        var h1 = new HashSet<int>();
        var h2 = new HashSet<int>();
        var ans = new List<int>();
        foreach (var i in nums1)
            h1.Add(i);
        foreach (var i in nums2)
            h2.Add(i);

        // 保证h1更短
        if (h1.Count > h2.Count) (h1, h2) = (h2, h1);

        foreach (var i in h1)
            if (h2.Contains(i))
                ans.Add(i);

        return ans.ToArray();
    }
}
// @lc code=end

由上一个题[LeetCode] 242.有效的字母异位词的经验,考虑过开一个数组来存,但是发现每个值的范围是0到1000,可能会有点浪费空间。

2.2 题解思路

349. 两个数组的交集 | 哈希表 | 集合

  • 使用数组来做哈希的题目,是因为题目都限制了数值的大小
  • 而且如果哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费
  • 好像leetcode原题是没有数值范围的,后面才加上去的,加上去后用数组空间效率更高

观察题目发现结果要求是去重的,那么可以用到set,在C#里的话,常用的是HashSet和SortedSet,前者使用散列法效率更高,后者使用红黑树

随想录给的思路如下,相比我之前的实现,可以少开一个HashSet,因为第二个数组直接比较就行其实差别不大(?)

img

C++:

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> result_set; // 存放结果,之所以用set是为了给结果集去重
        unordered_set<int> nums_set(nums1.begin(), nums1.end());
        for (int num : nums2) {
            // 发现nums2的元素 在nums_set里又出现过
            if (nums_set.find(num) != nums_set.end()) {
                result_set.insert(num);
            }
        }
        return vector<int>(result_set.begin(), result_set.end());
    }
};
  • 时间复杂度: O(n + m) m 是最后要把 set转成vector
  • 空间复杂度: O(n)

C#:好家伙,给库函数大人跪了,原来还有IntersectWith方法

public int[] Intersection(int[] nums1, int[] nums2) {
    if(nums1==null||nums1.Length==0||nums2==null||nums1.Length==0)
    	return new int[0]; //注意数组条件
    HashSet<int> one = Insert(nums1);
    HashSet<int> two = Insert(nums2);
    one.IntersectWith(two);
    return one.ToArray();
	}
 public HashSet<int> Insert(int[] nums){
    HashSet<int> one = new HashSet<int>();
    foreach(int num in nums){
    	one.Add(num);         
    	}
        return one;
	}

2.3 优化(或者敲一遍题解?)

那么根据理解敲一遍~

/*
 * @lc app=leetcode.cn id=349 lang=csharp
 *
 * [349] 两个数组的交集
 */

// @lc code=start
public class Solution
{
    public int[] Intersection(int[] nums1, int[] nums2)
    {
        if (nums1.Length == 0 || nums2.Length == 0) return Array.Empty<int>();
        var h1 = nums1.ToHashSet();
        var h2 = nums2.ToHashSet();
        h1.IntersectWith(h2);
        return h1.ToArray();
    }
}
// @lc code=end

原本想着防止重复造轮子,写个数组的扩展方法实现将数组转HashSet叭,结果智能感知直接跳出内置ToHashSet方法了……

关于这里的时间复杂度是怎么算的呢?

首先是将两个数组转为哈希表,分别是O(n)和O(m)

然后是求交集,是O(min(n, m))

然后加起来看低阶项:O(n) + O(m) + O(min(n, m))

在大 O 表示法中,我们只保留影响最大的项,并且忽略常数。min(n, m) 的增长速度绝对不会超过 n + m,所以它被低阶项吸收。

因此,最终的时间复杂度简写为:O(n + m)。


3. 补充知识と杂谈,总结

  • 那么这里又涉及到了该不该用库函数的问题

个人感觉对于算法题考查的东西还是少用,但如果是烂熟于心的东西可以用

  • 然后是算法题中要不要避免工程思维

因为个人相比算法来说,更喜欢架构设计,以前刚开始刷算法题的时候,动不动就新开一个类然后一套SOLID组合拳整上去。

但算法其实是针对一个类似原子模块的核心实现,不需要去过度设计,另外是防御性编程,这个倒是可以养成习惯写上去,基本的防NRE之类的

posted @ 2026-08-08 11:57  绘星tsuki  阅读(7)  评论(0)    收藏  举报