题目
给定两个数组,编写一个函数来计算它们的交集。
示例 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 的元素存储在磁盘上,磁盘内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?
分析
和两个数组的交集I 相比,这道题要求不去掉重复,而哈希表不能储存重复的key 上一题中哈希表key和value我们只用了一个key而已,所以这道题value再存个元素出现的次数就ojbk了
时间复杂度O(N)
空间复杂度O(N)
代码
public int[] Intersect(int[] nums1, int[] nums2) { if (nums1 == null || nums2 == null || nums1.Length == 0 || nums2.Length == 0) { return new int[] { }; } //调整nums1为小数组 if (nums1.Length > nums2.Length) { int[] temp = nums1; nums1 = nums2; nums2 = temp; } //存nums1所有不重复元素,与出现的次数 Dictionary<int, int> dic = new Dictionary<int, int>(); for (int i = 0; i < nums1.Length; i++) { if (!dic.ContainsKey(nums1[i])) { dic.Add(nums1[i], 0);//未出现过的元素,设置出现次数为0 } else { dic[nums1[i]]++;//已经存在 增加出现次数 } } //存nums2中含有nums1中的元素 也就是结果 List<int> list = new List<int>(); for (int i = 0; i < nums2.Length; i++) { //已经出现过的元素 并且出现的次数不小于0 if (dic.ContainsKey(nums2[i]) && dic[nums2[i]] >= 0) { list.Add(nums2[i]);//向List中添加该元素 dic[nums2[i]]--;//降低该元素的出现次数 } } //转换结果为数组 int[] result = new int[list.Count]; int j = 0; foreach (var item in list) { result[j] = item; j++; } return result; }
拓展1
如果给定的数组已经排好序呢?你将如何优化你的算法?
˼·
利用双指针,两个数组从0开始,
指针指向的元素相等时,两边同时向后移动,并添加一个该元素到结果中
不相等时移动元素小的指针
拓展2
如果 nums1 的大小比 nums2 小很多,哪种方法更优?
˼·
拓展1中的方法会更优秀
原题目的时间复杂度是O(nums1.Length+nums2.Length);
拓展1的时间复杂度是O(Min(nums.Length,nums2.Length));
不过前提是排好序,不然排序就要花费O(N*logN)的时间复杂度
拓展3
如果 nums2 的元素存储在磁盘上,磁盘内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?
˼·
排序后再用双指针做,以时间换空间.
文章来源: https://blog.csdn.net/qq_29799917/article/details/90437933