【LeetCode哈希表#2】两个数组的交集(Set+数组)
两个数组的交集
题意:给定两个数组,编写一个函数来计算它们的交集。
说明: 输出结果中的每个元素一定是唯一的。 我们可以不考虑输出结果的顺序。
思路
哈希表最擅长解决的一类问题是:
给一个元素,判断该元素在某个集合中是否出现过
本题也是非常符合哈希表的使用场景
选择合适的哈希表也是使用哈希方法时的关键
之前有提到,哈希表的实现大致有三类:数组、set、map
数组使用于长度有限的数据(最好是1000个以下),如果哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费。
而set则可用于大规模的数据(例如上亿级别)
本题在LeetCode更新后加了限制,因此可以用数组来做也可以用set来做
set
set这种数据结构在C++(std::set【红黑树】、std::multiset【红黑树】、std::unordered_set【哈希表】)和Java(主要是HashSet【数组+链表+红黑树】,当然还有别的实现类)中的特性是类似的
即:
-
set是无序的(添加和取出的顺序不一致),且没有索引
-
set中不允许有重复元素(会自动去重),因此最多包含一个null
-
set不能使用普通for循环遍历,要用迭代器或增强for循环
那么实际这题就变成了如何使用set接口的一个演示例题了
首先,新建一个set1,这里选用HashSet(cpp版本用unordered_set),遍历输入的nums1并存入set1
此时,set1中存放的数据就是去重后nums1中的元素
然后,再创建一个set2用于存放比较后的交集元素
遍历nums2,使用每个元素去set1中查询是否有相同的,有就保存到set2
数组
使用数组作为哈希表
遍历nums1,按当前元素在数组中对应下标处标记
如:
nums1 = {1,3,5,9}
↑
数组 = {0,1,0,...,0}
======================
nums1 = {1,3,5,9}
↑
数组 = {0,1,0,1,..,0}
======================
把nums1中所有元素在数组中标记后,当前数组就变成了一个哈希表。
输入为:"0~数组长度" 范围内的整数
输出为:一个布尔值,表示输入是否存在
之后,再用同样的方法遍历nums2,用遍历的元素作为下标到数组中查询,如果返回1,则将当前元素添加到一个set中(这样可以去除重复出现的元素)
代码
只使用set
Java版
import java.util.HashSet;
import java.util.Set;
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
Set<Integer> set1 = new HashSet<>();
Set<Integer> set2 = new HashSet<>();
//遍历nums1,将元素添加到set1
// //增强for
// for(int i : nums1){
// set1.add(i);
// }
for(int i = 0; i < nums1.length; i++){
set1.add(nums1[i]);
}
//遍历nums2,将所得元素与set1中的对比,相同则存入set2
////增强for
// for(int i : nums2){
// if(set1.contains(i)){
// set2.add(i);
// }
// }
for(int i = 0; i < nums2.length; i++){
if(set1.contains(nums2[i])){
set2.add(nums2[i]);
}
}
//将set转换为数组对象返回
return set2.stream().mapToInt(x -> x).toArray();
}
}
注意点:
1、使用set需要自行导入包
import java.util.HashSet;
import java.util.Set;
2、JavaAPI中Set接口常用方法
- .add,用于添加数据
- .contains,查询数据是否存在于set中
- .stream(),将源数据----包括集合、数组等转换成流
- .mapToInt(x -> x),将一个流中的元素转换为 int 类型
- .toArray(), 转换类型为一个数组(Object)
CPP版
待更新
数组
Java版
import java.util.HashSet;
import java.util.Set;
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
Set<Integer> set4save = new HashSet<>();
int[] hash = new int[1002];//题目限制了nums的大小在1000以下,因此数组可以设置1000左右
//遍历nums1,使用数组hash构建哈希表
for(int num : nums1){
hash[num] = 1;
}
//遍历nums2,用元素值作为下标查询哈希表
for(int num : nums2){
if(hash[num] == 1){
set4save.add(num);
}
}
//将set转换为数组对象返回
return set4save.stream().mapToInt(x -> x).toArray();
}
}
CPP版
使用数组
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
int hash[1001] = {0};
vector<int> res;
for(int num1 : nums1) hash[num1] = 1;
for(int num2 : nums2){
if(hash[num2] == 1){
hash[num2] = 0;
res.push_back(num2);
}
}
return res;
}
};