Java - 匹配两个无序列表

时间:2012-10-09 11:19:16

标签: java collections matching

我有以下问题:我需要在两个列表中找到相同元素的对,这两个列表是无序的。关于这两个列表的事情是它们“大致相等” - 只有某些元素被一些索引移动,例如(注意,这些对象不是整数,我只是在这个例子中使用整数):

[1,2,3,5,4,8,6,7,10,9]
[1,2,3,4,5,6,7,8,9,10]

我的第一次尝试是迭代两个列表,并根据每个对象的一些唯一键生成两个HashMaps。然后,在第二遍时,我只需从两个地图中拉出元素。这会在空间和时间上产生O(2N)

我正在考虑一种不同的方法:我们将保留指向两个列表中当前元素的指针,以及每个列表的当前未匹配集。伪代码将是以下类型:

while(elements to process)
    elem1 = list1.get(index1)
    elem2 = list2.get(index2)
    if(elem1 == elem2){ //do work
         ... index1++; 
             index2++;
    }
    else{
        //Move index of the list that has no unamtched elems
        if(firstListUnmatched.size() ==0){
            //Didn't find it also in the other list so we save for later 
            if(secondListUnamtched.remove(elem1) != true)
                firstListUnmatched.insert(elem1)
            index1++
        }
        else { // same but with other index}
    }

以上可能不起作用......我只是想大致了解你对这种方法的看法。基本上,这在每个列表的一侧维护一个散列集,其大小<<问题的大小。对于少量错位元素和小“间隙”,这应该是~O(N)。无论如何,我期待你的回复。

编辑:我不能简单地返回两个对象列表的集合交集,因为我需要对我发现匹配/不匹配的对象执行操作(甚至多个操作)

3 个答案:

答案 0 :(得分:1)

  

我不能简单地返回两个对象列表的集合交集,因为我需要对我发现匹配/不匹配的对象执行操作(甚至多个操作)

您可以维护一组不匹配的对象。这将是空间中的O(M),其中M是任何点处交换元素的最大数量。对于N是元素数的时间,它将是O(N)。

interface Listener<T> {
    void matched(T t1);
    void onlyIn1(T t1);
    void onlyIn2(T t2);
}

public static <T> void compare(List<T> list1, List<T> list2, Listener<T> tListener) {
    Set<T> onlyIn1 = new HashSet<T>();
    Set<T> onlyIn2 = new HashSet<T>();
    for (int i = 0; i < list1.size(); i++) {
        T t1 = list1.get(i);
        T t2 = list2.get(i);
        if (t1.equals(t2)) {
            tListener.matched(t1);
            continue;
        }
        if (onlyIn2.remove(t1)) 
            tListener.matched(t1);
         else 
            onlyIn1.add(t1);
        if (!onlyIn1.remove(t2))
            onlyIn2.add(t2);
    }
    for (T t1 : onlyIn1)
        tListener.onlyIn1(t1);
    for (T t2 : onlyIn2)
        tListener.onlyIn2(t2);
}

答案 1 :(得分:0)

如果我已正确理解您的问题,您可以使用Collection.retainAll然后迭代已保留的集合并执行您必须执行的操作。

list2.retainAll(list1);

答案 2 :(得分:0)

基于地图的所有方法最多都是O(n log(n)),因为创建地图是插入排序。效果是对两者进行插入排序,然后比较它们,这样就可以得到它。

如果列表几乎排序为开头,则排序步骤不应该与平均情况一样长,并且将与O(n log(n))一起缩放,因此只需对两者进行排序并进行比较。这使您可以根据需要单步执行匹配或不匹配的项目。