【LeetCode哈希表#2】两个数组的交集(Set+数组)

两个数组的交集

力扣题目链接(opens new window)

题意:给定两个数组,编写一个函数来计算它们的交集。

349. 两个数组的交集

说明: 输出结果中的每个元素一定是唯一的。 我们可以不考虑输出结果的顺序。

思路

哈希表最擅长解决的一类问题是:

给一个元素,判断该元素在某个集合中是否出现过

本题也是非常符合哈希表的使用场景

选择合适的哈希表也是使用哈希方法时的关键

之前有提到,哈希表的实现大致有三类:数组、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;
    }
};
posted @ 2023-01-24 21:11  dayceng  阅读(61)  评论(0编辑  收藏  举报