目录
一、 题目
题目:给定两个数组,编写一个函数来计算他们交集
二、 思路
直接用集合做
实现:新建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