【算法训练】day15数组交集(是否去重)

349. 两个数组的交集

给定两个数组 nums1 和 nums2 ,返回 它们的 交集。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]

示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的

提示:

  • 1 <= nums1.length, nums2.length <= 1000
  • 0 <= nums1[i], nums2[i] <= 1000

常规题,遍历nums1,存入哈希中,再看看nums2中的在哈希中是否存在,若存在则放入结果ret中。

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        if(nums1==null||nums2==null||nums1.length==0||nums2.length==0){
            return new int[0];
        }
        Set<Integer> set1 = new HashSet<>();
        Set<Integer> ret = new HashSet<>();
        //遍历nums1
        for(int num:nums1){
            set1.add(num);
        }
        //遍历nums2.判断哈希表中是否存在
        for(int num:nums2){
            if(set1.contains(num)){
                ret.add(num);
            }
        }
        //数组
        int[] retArr = new int[ret.size()];
        int i = 0;
        for(int num:ret){
            retArr[i++]=num;
        }
        return retArr;
    }
}

由于题目中限制了数组长度,所以提前开好长度可以节省时间,再用数组模拟来节省空间,如果用哈希的话就是用空间换时间。

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        int []hash=new int[1001];
        int []tmp=new int[1001];
        int count=0;
        for(int i=0;i<nums1.length;i++){
            hash[nums1[i]]=1;
        }
        for(int j=0;j<nums2.length;j++){
            if(hash[nums2[j]]==1){
                tmp[count++]=nums2[j];
                hash[nums2[j]]++;
            }
        }
        int []ret=new int[count];
        for(int k=0;k<count;k++){
            ret[k]=tmp[k];
        }
        return ret;
    }
}


350. 两个数组的交集 II

给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]

示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]

提示:

  • 1 <= nums1.length, nums2.length <= 1000
  • 0 <= nums1[i], nums2[i] <= 1000

进阶

  • 如果给定的数组已经排好序呢?你将如何优化你的算法?
  • 如果 nums1 的大小比 nums2 小,哪种方法更优?
  • 如果 nums2 的元素存储在磁盘上,内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?

和前面那题的区别就是,这个题要考虑重复数字问题。首先想到的就是哈希表了,进行记录。具体解释在代码中一注释。

class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        HashMap<Integer, Integer> map = new HashMap<>();
        ArrayList<Integer> list = new ArrayList<>();

        // 对nums1的数组遍历,存到map里面,key是数组元素值(对应map中的下标),value是出现次数
        for (int num : nums1) {
            map.put(num, map.getOrDefault(num, 0) + 1);
        }
        // 接着遍历nums2,如果上一轮中的value不为0,则进行结果存储并对该值进行减1操作
        for (int num : nums2) {
            if (map.getOrDefault(num, 0) > 0) {
                list.add(num);
                map.put(num, map.get(num) - 1);
            }
        }

        //转数组
        int[] ret = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            ret[i] = list.get(i);
        }
        return ret;
    }
}

 

在空间上还可以进行优化,我们可以保证map的大小是最小的数组的长度 ,加一个判断即可。

class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        if(nums1.length>nums2.length){
            return intersect(nums2,nums1);
        }
        HashMap<Integer, Integer> map = new HashMap<>();
        ArrayList<Integer> list = new ArrayList<>();

        // 对nums1的数组遍历,存到map里面,key是数组元素值(对应map中的下标),value是出现次数
        for (int num : nums1) {
            map.put(num, map.getOrDefault(num, 0) + 1);
        }
        // 接着遍历nums2,如果上一轮中的value不为0,则进行结果存储并对该值进行减1操作
        for (int num : nums2) {
            if (map.getOrDefault(num, 0) > 0) {
                list.add(num);
                map.put(num, map.get(num) - 1);
            }
        }

        //转数组
        int[] ret = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            ret[i] = list.get(i);
        }
        return ret;
    }
}

 用时间换空间,进行双层遍历(不实用)

class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < nums1.length; i++) {
            for (int j = 0; j < nums2.length; j++) {
                if (nums1[i] == nums2[j]){
                    list.add(nums1[i]);
                    nums2[j] = -1;
                    break;
                }
            }
        }
        int[] res = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            res[i] = list.get(i);
        }
        return res;
    }
}

 空间换时间,已知数组长度最大为1000,所以开1001长度的数组。

class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        int[] flag = new int[1001];//作为先遍历的标记数组
        for (int num : nums1) {
            flag[num]++;
        }

        int[] tmp = new int[1001];//中间数组,暂时存储
        int length = 0;//记录长度
        for (int num : nums2) {
            if (flag[num] > 0) {
                tmp[length++] = num;
                flag[num]--;
            }
        }
        //去掉多余的0
        int[] ret = new int[length];
        System.arraycopy(tmp, 0, ret, 0, length);
        return ret;
    }
}

 

yeah!完结! 

可以使用多种方法来获取Python数组交集。 方法一:使用列表推导式in操作符 ```python a = [2, 3, 4, 5] b = [2, 5, 8] tmp = [val for val in a if val in b] print(tmp) # [2, 5] ``` 方法二:使用set的intersection方法 ```python a = [2, 3, 4, 5] b = [2, 5, 8] print(list(set(a).intersection(set(b)))) # [2, 5] ``` 方法三:使用集合交集运算符& ```python a = [2, 3, 4, 5] b = [2, 5, 8] print(list(set(a) & set(b))) # [2, 5] ``` 以上是三种常见的方法获取Python数组交集。你可以根据实际情况选择其中一种方法来使用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Python 获得两个数交集、并集、差集的方法](https://blog.youkuaiyun.com/sunny_day_day/article/details/126208046)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [两个数组的交集Python解法](https://blog.youkuaiyun.com/qq_43593534/article/details/127178466)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Echo-Nie

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值