【详细整理】排序第三题——349 两个数组的交集

一、 题目

题目:给定两个数组,编写一个函数来计算他们交集

二、 思路

直接用集合做
实现:新建list数组,遍历nums1,统计其中出现的元素,再遍历nums2 如果其中元素list中含有,则输出。

三、初始代码

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        ArrayList<Integer> list = new ArrayList<>();        
        for(int num : nums1){
            list[num]++;
        }
        int []list2=new int[(nums1.length<nums2.length?nums1.length:nums2.length)];
        for(int num : nums2){
            if(list[num]>0){
                list2[i++]=num;
                list.remove(num);
            }
        }
        return list2;
    }
}

四、调试过程bug分析

bug 1

在这里插入图片描述
list不能用list[num]++吗,而且这样存在一个问题,如果num很大,list分配的空间 就会很大。(想了想这里弄混了,是桶和HashMap使用元素做索引,list是有序储存元素,不是依靠元素的对应关系)
向list中增加元素:list.add

 list.add(num);

然后后面用list.contains(num)查看List中是否含有num元素。

bug 2

在这里插入图片描述
出现了两次,remove不成功吗,不对 ,是remove了一个还有一个,怎么样删去重复元素呢?

if(list.contains(num)&&(list2.contains(num)==0))

这样就可以,但是报错list2 是数组 不能使用contains函数。改一下类型

bug 3

在这里插入图片描述
不能比较boolean和int ,boolean结果应该是false 或者true 改为

if(list.contains(num)&&(list2.contains(num)==false)){

bug 4

在这里插入图片描述
List 不能直接作为数组返回

int [] list3=new int[list2.size()];
        for(int i=0;i<list3.length;i++){
            list3[i]=list2.get(i);
        }
        return list3;

获取list中的元素用get()函数

bug 5

在这里插入图片描述

但是提交的时候发现出错了:
在这里插入图片描述

List.remove(num)移除的是index=num的值,第一题能运行成功真是瞎猫碰上死耗子。
移除元素应该用…
查了下,不是这样的,remove()移除的就是其中的元素,不过这里有个冲突,因为传入的是int 数据
remove有以下两种定义:

public E remove(int index); 
public boolean remove(Object o);

当\传入int类型的时候,会自动被当成上面那个方法来调用。而下面那个移除某个特定元素的方法是需要传入一个Object对象。
所以为了不引起混淆,将传入的Int 进行封装

list.remove((Integer)num);

五、 最终代码结果

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        ArrayList<Integer> list = new ArrayList<>();
        ArrayList<Integer> list2 = new ArrayList<>();
        for (int num : nums1){
            list.add(num);
        }
        // int []list2=new int[(nums1.length<nums2.length?nums1.length:nums2.length)];
        // int i = 0;
        for (int num : nums2){
            if (list.contains(num)&&(list2.contains(num)==false)){
                // list2[i++]=num;
                list2.add(num);
                // list.remove(num);
                list.remove((Integer)num);
            } 
        }
        // return list2;
        int [] list3=new int[list2.size()];
        for(int i=0;i<list3.length;i++){
            list3[i]=list2.get(i);
        }
        return list3;
    }
}

在这里插入图片描述
运行时间太长了,因为创建了两个数组,做了两个遍历。

六、官方解答

(1)代码

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> set1 = new HashSet<Integer>();
        Set<Integer> set2 = new HashSet<Integer>();
        for (int num : nums1) {
            set1.add(num);
        }
        for (int num : nums2) {
            set2.add(num);
        }
        return getIntersection(set1, set2);
    }
    public int[] getIntersection(Set<Integer> set1, Set<Integer> set2) {
        if (set1.size() > set2.size()) {
            return getIntersection(set2, set1);
        }
        Set<Integer> intersectionSet = new HashSet<Integer>();
        for (int num : set1) {
            if (set2.contains(num)) {
                intersectionSet.add(num);
            }
        }
        int[] intersection = new int[intersectionSet.size()];
        int index = 0;
        for (int num : intersectionSet) {
            intersection[index++] = num;
        }
        return intersection;
    }
}

(2) 分析

在这里插入图片描述
官方的运行了一下,时间很短,分析了一下:

官方解答其实思路跟我的是一样的,创建集合放置数组元素,遍历另一个数组,返回相同的元素,官方解答几个减少时间复杂度的点:
1、使用HashSet,避免重复元素的添加,时间复杂度为O(1)
2、用了一个非常妙的if条件的循环调用使得遍历的是小数组,减少时间复杂度
3、可以加一个边界条件

七、 HashSet理论

数据结构只看了一点排序,一边做题一边学。

HashSet以对象作为元素,元素没有放入的顺序,且拒绝重复元素(插入和删除效率高,但检索效率低。跟Arraylist相反,list元素有顺序,可重复,检索效率高但是删除和插入的效率就会比较低)。HashMap以一组对象作为元素(key和它映射的value)。

“HashMap可以看作三个视图:key的Set,value的Collection,Entry的Set。 这里HashSet就是其实就是HashMap的一个视图。”Entry是啥没看懂,不过这就是说HashSet的底层是HashMap,维度不一样罢了。
增加元素用add

八、 HashMap:

Hashmap是一个数组和链表的结合体(在数据结构称“链表散列“)

当我们往hashmap中put元素的时候,先根据key的hash值得到这个元素在数组中的位置(即下标),然后就可以把这个元素放到对应的位置中了。如果这个元素所在的位子上已经存放有其他元素了,那么在同一个位子上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。

存入元素用put() 读取元素用get(),判断是否存在键 containsKey()

写在后面

整理充满满足感,大家有什么想法欢迎交流

HashSet理论部分来源:link

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值