【发布时间】:2012-09-06 14:25:05
【问题描述】:
如果我有两个有序的数字序列(我在这里有很大的灵活性,可以将我的数据放在列表、集合、数组等中),那么提取匹配项最有效的方法是什么?例如,如果我有:
[1, 2, 4, 6, 9]和[2, 3, 4],我想回[2, 4]。
显然有很多方法可以解决这个问题;我很好奇最有效的方法是什么。
【问题讨论】:
-
序列可以包含重复的数字吗?
如果我有两个有序的数字序列(我在这里有很大的灵活性,可以将我的数据放在列表、集合、数组等中),那么提取匹配项最有效的方法是什么?例如,如果我有:
[1, 2, 4, 6, 9]和[2, 3, 4],我想回[2, 4]。
显然有很多方法可以解决这个问题;我很好奇最有效的方法是什么。
【问题讨论】:
两个指针(索引),每个列表一个。从每个列表的开头开始
只要找到匹配项,就将其存储起来。
如果没有匹配项,请检查哪个列表在当前索引中具有最低值并增加该列表的索引。检查匹配。这样做直到您到达列表之一的末尾。
与列表总和的大小成线性关系(更糟糕的情况)。没有办法做得更好。
【讨论】:
所以你想要 to 集合的交集? 您可以使用来自 apache commons 的 CollectionUtils.intersection。或者更好的是来自 Guava Sets.intersection 的那个(这是通用的)。
【讨论】:
如果您将这两个序列存储到 Sets 中,您可以使用 Set.retainAll() 其中:
仅保留此集合中包含在指定集合中的元素(可选操作)。换句话说,从这个集合中移除所有不包含在指定集合中的元素。如果指定的集合也是一个集合,则此操作有效地修改此集合,使其值为两个集合的交集。
例如:
Set<Integer> s1 = new TreeSet<Integer>();
s1.add(1);
s1.add(2);
s1.add(6);
Set<Integer> s2 = new TreeSet<Integer>();
s2.add(2);
s2.add(6);
s2.retainAll(s1);
for (Integer i: s2)
{
System.out.println(i);
}
输出:
2 6【讨论】:
Hashset 它自己。
这是intersection 的两个集合,我猜Set 是最好的选择。
仅保留此集合中包含在指定集合中的元素(可选操作)。换句话说,从这个集合中移除所有不包含在指定集合中的元素。
更有效的方法是
public static void main(String[] args) {
int[] firstArray = { 1, 3, 5, 8, 10 };
int[] secondArary = { 3, 8 };
//Arrays.sort(firstArray); If arrays needs to be sorted
//Arrays.sort(secondArary);
System.out.println(Arrays
.toString(intersection(firstArray, secondArary)));
}
private static Integer[] intersection(int firstArray[], int secondArary[]) {
int i = 0;
int j = 0;
ArrayList<Integer> list = new ArrayList<Integer>();
while (i < firstArray.length && j < secondArary.length) {
if (firstArray[i] < secondArary[j])
i++;// Increase I move to next element
else if (secondArary[j] < firstArray[i])
j++;// Increase J move to next element
else {
list.add(secondArary[j++]);
i++;// If same increase I & J both
}
}
return list.toArray(new Integer[0]);
}
【讨论】:
我会将这两个列表创建为java.util.Set,将一组复制到一个临时变量并在这个临时集上调用retainAll(<otherSet>)。那么临时集合将留在两个集合的交集处。
【讨论】:
我会使用TreeLists 并执行以下操作:
TreeList<Integer> list1 = ...
TreeList<Integer> list2 = ...
Iterable<Integer> result = Iterables.filter(list1, Predicates.in(list2));
这使用 Guava 的 Iterables 和 Predicates。
【讨论】: