Java 从2个链接列表中删除重复项

Java 从2个链接列表中删除重复项,java,Java,我在一次采访中被问到这个问题 LinkedList A有{1,2,3,4,5,6} LinkedList B有{1,3,5} 我需要编写一个方法,返回不包含列表a和B中重复元素的集合 结果{2,4,6} 我编写了一个迭代第一个列表的解决方案,如果第二个列表中不存在,则将其添加到哈希集中。但是需要一个比建议的算法性能更好的解决方案 没有提到解决此问题的空间约束 我肯定会喜欢使用JDK的解决方案,但我更喜欢基于算法的解决方案 非常感谢,标准的解决方案是循环第一个列表并将所有内容放入哈希表中。这是线性

我在一次采访中被问到这个问题

LinkedList A有{1,2,3,4,5,6}

LinkedList B有{1,3,5}

我需要编写一个方法,返回不包含列表a和B中重复元素的集合

结果{2,4,6}

我编写了一个迭代第一个列表的解决方案,如果第二个列表中不存在,则将其添加到哈希集中。但是需要一个比建议的算法性能更好的解决方案

没有提到解决此问题的空间约束

我肯定会喜欢使用JDK的解决方案,但我更喜欢基于算法的解决方案


非常感谢,标准的解决方案是循环第一个列表并将所有内容放入哈希表中。这是线性时间,因为插入哈希表的时间是常数时间

然后循环第二个列表,查看哈希表中是否存在每个元素。如果存在,请将其从表中删除。否则,将此项目添加到新列表中

现在将哈希表中剩余的所有内容追加到新列表中

第二个操作也是线性的,因为哈希表的查找和删除也是常量。因此,整个算法是线性的。

Integer[]a1={1,2,3,4,5,6};
    Integer[] a1 = {1,2,3,4,5,6};
    Integer[] a2 = {1,3,5,8};

    LinkedList<Integer> ll1 = new LinkedList(Arrays.asList(a1));
    LinkedList<Integer> ll2 = new LinkedList(Arrays.asList(a2));

    Set<Integer> set1 = new HashSet<Integer>(ll1);
    Set<Integer> set2 = new HashSet<Integer>(ll2);
    set1.removeAll(ll2);
    set2.removeAll(ll1);
    set1.addAll(set2);

    System.out.println(set1);
整数[]a2={1,3,5,8}; LinkedList ll1=新的LinkedList(Arrays.asList(a1)); LinkedList ll2=新的LinkedList(Arrays.asList(a2)); Set set1=新哈希集(ll1); Set set2=新哈希集(ll2); set1.移除所有(ll2); set2.移除所有(ll1); set1.addAll(set2); 系统输出打印项次(set1);

removeAll()是子动作,addAll()是集合的并集。

这取决于面试的职位。他们可能对你的逻辑感兴趣。一个可能的解决方案是从一个简单的方法开始:

public Set<Integer> killDuplicates(LinkedList<Integer> a0, LinkedList<Integer> a1) {
        Set<Integer> common = new HashSet<Integer>();
        common.addAll(a0); //one could pass thru constructor, no matter
        common.retainAll(a1);
        Set<Integer> result = new HashSet<Integer>();
        result.addAll(a0);
        result.addAll(a1);
        result.removeAll(common);
        return result;
    }
公共集重复(LinkedList a0、LinkedList a1){
Set common=new HashSet();
common.addAll(a0);//不管怎样,都可以通过构造函数
普通。保留(a1);
Set result=new HashSet();
结果:addAll(a0);
结果:addAll(a1);
结果:removeAll(普通);
返回结果;
}
但在某些情况下,这可能会非常缓慢,并且有很多方法可以提高代码的速度。 一种可能的解决方案是使用特殊的结构进行快速集合交叉

排序很好,但因为我们在LL中有数据,所以它将使用合并排序(用伪代码编写的额外内存,但可以自由提问):

公共集已复制(…){
//排序a0
//a1类
迭代器i0=a0.getIterator();
迭代器i1=a1.getIterator();
while(i0!=end&&i1!=end){
如果(i0.current==i1.current){
//这两种语言都有skip
i0.moveNext();
i1.moveNext();
}否则如果(i0.电流
在Scala中,如前所述,使用内部映射,然后循环

scala> val x = (1 to 6).toList
x: List[Int] = List(1, 2, 3, 4, 5, 6)

scala> val y = (1 to 5 by 2).toList
y: List[Int] = List(1, 3, 5)

scala> val result = x.diff(y).toSet
result: scala.collection.immutable.Set[Int] = Set(2, 4, 6)

这将给我输出{1,2,3,4,5,6,8},但我希望输出为{2,4,6,8}@bhargava抱歉,我没有马上理解你。我修正了代码,这是常数时间解吗?我这样认为的原因是,假设hashcode得到了正确实现,hashset中的添加和删除操作都是固定时间的。我不确定。Set set1=新哈希集(ll1);使用LinkedList的迭代器。列表迭代器似乎有O(n)。可能我错了。合并排序需要O(n*log(n))时间。线性时间排序是不可能的,因为OP没有提到我们是否可以使用计数排序或基数排序。合并排序可能是解决此问题的最佳方法。假设L1由非常大的数字组成(即1.XXXX*pow(2,30+)。然后,任何真正好的散列函数都将采用顺序(bitsizeof(verylargenumber))。因此,哈希函数解决方案将花费比O(N)更多的时间,而不是0(非线性时间)。因此,在某些涉及非常大的数字的情况下,mergesort的答案可能会优于哈希解决方案。值得补充的是,这并不完全是线性时间,但平均情况下是线性时间。请参阅:@dahunter,因为它依赖于散列函数?请查看对各种
removeAll()
实现的分析
scala> val x = (1 to 6).toList
x: List[Int] = List(1, 2, 3, 4, 5, 6)

scala> val y = (1 to 5 by 2).toList
y: List[Int] = List(1, 3, 5)

scala> val result = x.diff(y).toSet
result: scala.collection.immutable.Set[Int] = Set(2, 4, 6)