题目:
给定两个数组,编写一个函数来计算它们的交集。
示例
- 示例 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 的元素存储在磁盘上,磁盘内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?
抛砖引玉
- 遍历其中一个数组 nums1 在另外一个数组 nums2 红检查是否存在该元素
- 存在放入结果中,并在 nums2 中清除
- 不存在则不作任何操作
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number[]}
*/
var intersect = function (nums1, nums2) {
let _result = []
for (let i = 0; i < nums1.length; i++) {
let index = nums2.indexOf(nums1[i])
if (index > -1) {
_result.push(nums1[i])
nums2.splice(index, 1)
}
}
return _result
}
官方答案:
- 哈希表
- 利用 map 记录较短数组中每个数组出现的次数
- 遍历较长数组到 map 中检查这个数组是否在 map 中且遇到次数不为 0
- 次数大于 0,存放到结果数组中,且更新 map 中统计的个数
- 小于等 0,则这个数字在较短数组没出现
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number[]}
*/
var intersect = function (nums1, nums2) {
if (nums1.length > nums2.length) {
return intersect(nums2, nums1)
}
let map = new Map()
for (let i = 0; i < nums1.length; i++) {
let count = (map.get(nums1[i]) || 0) + 1
map.set(nums1[i], count)
}
let _result = []
for (let i = 0; i < nums2.length; i++) {
let count = map.get(nums2[i]) || 0
if (count > 0) {
_result.push(nums2[i])
map.set(nums2[i], count - 1)
}
}
return _result
}
- 排序
- 先对两个数组排序优化循环
- 从零遍历两个数组,比较两个数组不用指针下的元素大小
- 其中一个数组当前指针下数字小,则后移指针去查询到比另外一个数组指针下等于小于其的数
- 两数相同记录到结果中切两个指针同时后移
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number[]}
*/
var intersect = function (nums1, nums2) {
nums1.sort((a, b) => a - b)
nums2.sort((a, b) => a - b)
let len1 = nums1.length,
len2 = nums2.length,
_result = [],
i = 0,
j = 0,
index = 0
while (i < len1 && j < len2) {
if (nums1[i] < nums2[j]) {
i++
} else if (nums1[i] > nums2[j]) {
j++
} else {
_result[index] = nums1[i]
i++
j++
index++
}
}
return _result
}
博客: 小书童博客
公号: 坑人的小书童