原理
代码通过哈希数组统计元素出现的次数,找出两个数组中共同存在的元素。核心思路是:
- 哈希数组映射:用两个数组
hash1
和hash2
分别记录nums1
和nums2
中每个元素的出现次数。 - 交集判断:遍历哈希数组,若某个元素在两个哈希数组中的计数均不为零,说明它是交集元素。
步骤
-
初始化哈希数组:
- 创建两个长度为
1001
的数组hash1
和hash2
,初始值全为0
。 - 因为题目中元素范围为
[0, 1000]
,哈希数组的索引直接对应元素值,值对应出现次数。
- 创建两个长度为
-
统计元素出现次数:
- 遍历
nums1
,将每个元素的值作为索引,在hash1
中对应的位置计数+1
。 - 同样遍历
nums2
,更新hash2
。
- 遍历
-
找出交集元素:
- 遍历哈希数组
hash1
(或hash2
,因为长度相同),检查每个索引i
。 - 如果
hash1[i]
和hash2[i]
均不为零,说明i
是两个数组的交集元素,将其加入结果。
- 遍历哈希数组
图示
假设输入为 nums1 = [1, 2, 2, 1]
,nums2 = [2, 2]
:
-
统计哈希数组:
hash1[1] = 2
,hash1[2] = 2
,其余为0
。hash2[2] = 2
,其余为0
。
-
遍历哈希数组:
- 检查索引
0
到1000
,发现只有索引2
满足hash1[2] != 0
且hash2[2] != 0
。 - 将
2
加入结果。
- 检查索引
最终结果:[2]
。
代码关键行注释
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
vector<int> ans;
vector<int> hash1(1001, 0); // 哈希数组1,记录nums1中元素的出现次数
vector<int> hash2(1001, 0); // 哈希数组2,记录nums2中元素的出现次数
// 遍历nums1,统计元素出现次数
for (int i = 0; i < nums1.size(); i++) {
hash1[nums1[i]]++; // nums1的元素值作为索引,计数+1
}
// 遍历nums2,统计元素出现次数
for (int i = 0; i < nums2.size(); i++) {
hash2[nums2[i]]++; // nums2的元素值作为索引,计数+1
}
// 遍历哈希数组,找出交集元素
for (int i = 0; i < hash1.size(); i++) { // 哈希数组长度为1001
if (hash1[i] != 0 && hash2[i] != 0) { // 两个数组均包含该元素
ans.push_back(i); // 将元素值i加入结果
}
}
return ans;
}
完整代码
#include <iostream>
#include <istream>
#include <vector>
#include <sstream>
#include <string>
using namespace std;
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
vector<int> ans;
vector<int> hash1(1001, 0);
vector<int> hash2(1001, 0);
for (int i = 0; i < nums1.size(); i++) {
hash1[nums1[i]]++;
}
for (int i = 0; i < nums2.size(); i++) {
hash2[nums2[i]]++;
}
for (int i = 0; i < hash1.size(); i++) {
if (hash1[i] != 0 && hash2[i] != 0) {
ans.push_back(i);
}
}
return ans;
}
int main() {
vector<int> nums1;
string line1;
getline(cin, line1);
istringstream iss1(line1);
int num1;
while (iss1 >> num1) {
nums1.push_back(num1);
}
vector<int> nums2;
string line2;
getline(cin, line2);
istringstream iss2(line2);
int num2;
while (iss2 >> num2) {
nums2.push_back(num2);
}
vector<int> ans = intersection(nums1, nums2);
for (int i = 0; i < ans.size(); i++) {
cout << ans[i] << " ";
}
return 0;
}
时间复杂度
- 统计哈希数组:
- 遍历
nums1
和nums2
,时间复杂度为 O(n + m),其中n
和m
是数组长度。
- 遍历
- 遍历哈希数组:
- 哈希数组长度为
1001
,时间复杂度为 O(1001)。
- 哈希数组长度为
- 总时间复杂度:O(n + m + 1001),即线性复杂度。
总结
-
优点:
- 代码简洁高效,适用于元素范围明确且较小的情况(如
[0, 1000]
)。 - 哈希数组直接通过索引访问,查询时间为
O(1)
。
- 代码简洁高效,适用于元素范围明确且较小的情况(如
-
局限性:
- 元素范围必须已知且较小,无法处理负数或超过
1000
的值。 - 哈希数组固定长度为
1001
,可能浪费内存(例如数组中只有少数元素时)。
- 元素范围必须已知且较小,无法处理负数或超过
-
适用场景:
- 明确元素范围(如题目中给定数值范围)时,此方法是理想选择。
- 需要快速实现且不追求通用性时,可直接使用此代码。