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

时间:2011-11-08 03:48:27

标签: java

我在接受采访时被问到这个问题

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

LinkedList B有{1,3,5}

我需要编写一个方法,它会返回一个不包含列表A和B中重复元素的Set

结果{2,4,6}

我编写了一个解决方案,它将迭代第一个列表,如果它不存在于第二个列表中,则将其添加到HashSet中。但需要一种性能优于建议算法的解决方案。

没有提到解决此问题的空间限制。

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

非常感谢

5 个答案:

答案 0 :(得分:4)

标准解决方案是遍历第一个列表并将所有内容放在哈希表中。这是线性时间,因为插入哈希表是恒定时间。

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

现在将哈希表中剩下的所有内容附加到新列表中。

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

答案 1 :(得分:1)

查看分析了各种removeAll()实现

this blog post

答案 2 :(得分:1)

这取决于您接受采访的位置。他们可能对你的逻辑很感兴趣。一种可能的解决方案是从一个简单的方法开始:

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;
    }

但在某些情况下,这仍然会非常缓慢,并且有很多方法可以提高此代码的速度。 一种可能的解决方案是使用特殊结构进行快速交叉。

排序很好,但由于我们在LL中有数据,它会使用合并排序(附加内存用伪代码编写但随意提问):

public Set<Integer> killDuplicatesSorted(...) {
    //sort a0
    //sort a1
    Iterator i0 = a0.getIterator();
    Iterator i1 = a1.getIterator();
    while (i0 != end && i1 != end) {
        if (i0.current == i1.current) {
            //skip presented in both
            i0.moveNext();
            i1.moveNext();
        } else if (i0.current < i1.current) {
            result.add(i0.current);
            i0.moveNext();
        } else {
            result.add(i1.current);
            i1.moveNext();
        }
    }
    while (i0 != end) {result.add(i0.current); i0.moveNext();}
    while (i1 != end) {result.add(i1.current); i1.moveNext();}
    return result;
}

答案 3 :(得分:0)

    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);

removeAll()是子操作,addAll()是集合的联合。

答案 4 :(得分:0)

在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)