我有以下问题:我需要在两个无序列表中找到成对的相同元素。关于这两个列表的事情是它们“大致相等” - 只有某些元素被几个索引移动,例如(注意,这些对象不是整数,我在这个例子中只是使用整数):
[1,2,3,5,4,8,6,7,10,9]
[1,2,3,4,5,6,7,8,9,10]
我的第一个尝试是遍历两个列表并根据每个对象的一些唯一键生成两个 HashMap。然后,在第二遍时,我会简单地从两个 map 中提取元素。这会在空间和时间上产生 O(2N)
。
我在考虑一种不同的方法:我们将在两个列表中保留指向当前元素的指针,以及为每个列表设置的 currentlyUnmatched。伪代码将是以下类型的某物:
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)。无论如何,我期待您的回复。
编辑:我不能简单地返回两个对象列表的集合交集,因为我需要对我发现匹配/不匹配的对象执行操作(甚至多次操作)
最佳答案
I cannot simply return a set intersection of two object lists, as I need to perform operations (multiple operations even) on the objects I find as matching/non-matching
您可以维护一组不匹配的对象。这将是空间中的 O(M),其中 M 是任意一点交换元素的最大数量。时间复杂度为 O(N),其中 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);
}
关于Java - 匹配两个无序列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12798911/